Add Web Viewer container uploads - #300
Conversation
- Document container read and write workflows - Add upload limits, timeout, and script configuration
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: b4dbd5b The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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 |
@proofkit/better-auth
@proofkit/fmdapi
@proofkit/fmodata
@proofkit/typegen
@proofkit/webviewer
commit: |
📝 WalkthroughWalkthroughThe change adds configurable Base64 container uploads to ChangesContainer upload support
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant WebViewerApp
participant WebViewerAdapter
participant PK_container_upload
WebViewerApp->>WebViewerAdapter: Call containerUpload with file and record metadata
WebViewerAdapter->>WebViewerAdapter: Validate and encode the file
WebViewerAdapter->>PK_container_upload: Send record metadata and Base64 payload
PK_container_upload-->>WebViewerAdapter: Return success or FileMaker error
WebViewerAdapter-->>WebViewerApp: Resolve or reject the upload
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 8
🧹 Nitpick comments (4)
packages/webviewer/src/adapter.ts (1)
90-92: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueUse arrow functions for the short helper functions.
Convert
containerTimeoutMessage,blobToBase64,getUploadFileName,resolveContainerRepetition, andresolveContainerOptionstoconstarrow functions.As per coding guidelines, use arrow functions for callbacks and short functions.
Also applies to: 113-162
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/webviewer/src/adapter.ts` around lines 90 - 92, Convert the short helper functions containerTimeoutMessage, blobToBase64, getUploadFileName, resolveContainerRepetition, and resolveContainerOptions from function declarations to const-assigned arrow functions, preserving their parameters, return types, and existing behavior.Source: Coding guidelines
apps/docs/content/docs/webviewer/containers.mdx (2)
202-209: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueReplace the indexed loop in the sample.
The coding guidelines prefer
for...ofover indexedforloops.Uint8Array.fromremoves the loop entirely and keeps the sample shorter.♻️ Proposed refactor
export function base64ToBlobUrl(base64: string, mimeType: string) { const binary = atob(base64); - const bytes = new Uint8Array(binary.length); - for (let index = 0; index < binary.length; index++) { - bytes[index] = binary.charCodeAt(index); - } + const bytes = Uint8Array.from(binary, (character) => character.charCodeAt(0)); return URL.createObjectURL(new Blob([bytes], { type: mimeType })); }As per coding guidelines: "Prefer
for...ofloops over.forEach()and indexedforloops".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/docs/content/docs/webviewer/containers.mdx` around lines 202 - 209, Update base64ToBlobUrl to remove the indexed loop by constructing the Uint8Array with Uint8Array.from over the decoded binary string, preserving the existing byte conversion and Blob URL behavior.Source: Coding guidelines
58-62: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winScope the table rows to
container.*.
scriptNameis also a top-level Data API option. Prefix the rows withcontainer.. The adapter defaults and0semantics match the documented values.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/docs/content/docs/webviewer/containers.mdx` around lines 58 - 62, Update the option names in the table to use the container namespace: rename scriptName, timeoutMs, and maxFileBytes to container.scriptName, container.timeoutMs, and container.maxFileBytes while preserving their existing defaults and notes.packages/webviewer/tests/adapter.test.ts (1)
817-831: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low valueExtract the container timeout into a named constant.
beforeEachalready enables fake timers. Use atimeoutMsconstant for both the adapter configuration andvi.advanceTimersByTimeAsync.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/webviewer/tests/adapter.test.ts` around lines 817 - 831, Define a named timeoutMs constant within the “times out with an add-on upgrade hint when the script never calls back” test, then reuse it for the adapter’s container.timeoutMs configuration and vi.advanceTimersByTimeAsync call instead of duplicating the literal value.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.changeset/webviewer-container-upload.md:
- Line 2: Run pnpm run ci from the repository root before completing the
changes, and resolve any formatting, lint, or TypeScript type-check failures
reported for the webviewer and documentation updates.
In `@apps/docs/content/docs/webviewer/containers.mdx`:
- Around line 262-268: Update the sample script’s success branch after Set Field
so Get ( LastError ) is captured immediately before Commit Records/Requests, and
use that captured value to determine ok and error. Preserve the not-found
branch, and emit the error field only when the captured error is nonzero rather
than setting it to 0 on success.
- Around line 311-330: Declare or import OTTO_DATA_API_KEY in the otto-upload.ts
sample before uploadViaOttoFMS, showing that it is supplied through the
application’s public configuration or initial props. Keep the existing fetch
authorization usage unchanged and ensure copied code does not reference an
undefined value.
- Line 332: Update the OttoFMS upload description to use the storage pattern
Data/Documents/otto/:channel/:uuid/filename, remove the claim that uploads are
deleted after 24 hours, and extend the uploaded_files entry fields with
filename, fieldname, encoding, and destination while preserving the valid
OttoReceiver, existing fields, and file-insertion guidance.
In `@packages/webviewer/specs/container-upload-script.md`:
- Line 100: Update the fenced code block in the container upload script
documentation to specify the text language identifier, resolving the
markdownlint warning while preserving the existing FileMaker pseudocode content.
- Around line 103-127: Complete the script flow around the envelope parsing and
callback construction by extracting and validating modId and repetition,
resolving the empty webViewerName fallback, and assigning $result with code "0"
only after successful navigation, field write, and commit; otherwise build the
documented failure envelope. Ensure every failure path closes the temporary
window before invoking SendCallBack, and preserve the callback contract expected
by WebViewerAdapter.handleDataApiResponse().
In `@packages/webviewer/src/adapter.ts`:
- Around line 126-134: Update getUploadFileName to require a nonempty extension
after the filename’s final dot before returning fileName. Reject names without a
final dot or with no characters after it, while preserving the existing
validation for missing or blank filenames and its error behavior.
- Around line 665-669: Update the timeout handling in the containerUpload flow
around withTimeout so a local timeout reports an unknown upload outcome rather
than claiming the FileMaker script did not respond, while preserving the
existing timeout behavior. In
packages/webviewer/specs/container-upload-script.md:155-159, define a request
identity with idempotency or status lookup semantics so delayed completion can
be reconciled and callers do not retry unsafely; update both sites as part of
the same contract.
---
Nitpick comments:
In `@apps/docs/content/docs/webviewer/containers.mdx`:
- Around line 202-209: Update base64ToBlobUrl to remove the indexed loop by
constructing the Uint8Array with Uint8Array.from over the decoded binary string,
preserving the existing byte conversion and Blob URL behavior.
- Around line 58-62: Update the option names in the table to use the container
namespace: rename scriptName, timeoutMs, and maxFileBytes to
container.scriptName, container.timeoutMs, and container.maxFileBytes while
preserving their existing defaults and notes.
In `@packages/webviewer/src/adapter.ts`:
- Around line 90-92: Convert the short helper functions containerTimeoutMessage,
blobToBase64, getUploadFileName, resolveContainerRepetition, and
resolveContainerOptions from function declarations to const-assigned arrow
functions, preserving their parameters, return types, and existing behavior.
In `@packages/webviewer/tests/adapter.test.ts`:
- Around line 817-831: Define a named timeoutMs constant within the “times out
with an add-on upgrade hint when the script never calls back” test, then reuse
it for the adapter’s container.timeoutMs configuration and
vi.advanceTimersByTimeAsync call instead of duplicating the literal value.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 42272634-5c91-4930-87e4-d3bb281eea8a
📒 Files selected for processing (7)
.changeset/webviewer-container-upload.mdapps/docs/content/docs/webviewer/containers.mdxapps/docs/content/docs/webviewer/meta.jsonapps/docs/content/docs/webviewer/runtime-under-the-hood.mdxpackages/webviewer/specs/container-upload-script.mdpackages/webviewer/src/adapter.tspackages/webviewer/tests/adapter.test.ts
| If [ Get ( FoundCount ) = 0 ] | ||
| Set Variable [ $result ; Value: JSONSetElement ( "" ; [ "ok" ; False ; JSONBoolean ] ; [ "error" ; "Record not found" ; JSONString ] ) ] | ||
| Else | ||
| Set Field [ Customers::Photo ; Base64Decode ( $base64 ; $fileName ) ] | ||
| Commit Records/Requests [ With dialog: Off ] | ||
| Set Variable [ $result ; Value: JSONSetElement ( "" ; [ "ok" ; Get ( LastError ) = 0 ; JSONBoolean ] ; [ "error" ; Get ( LastError ) ; JSONNumber ] ) ] | ||
| End If |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
The sample script reports success when Set Field fails.
The script captures Get ( LastError ) only after Commit Records/Requests. If Base64Decode or the Set Field step fails, the commit can still return 0, so the script returns ok: true. Capture the error right after Set Field.
The script also sets error to 0 on success. Set error only on failure so the documented error?: number | string type stays meaningful.
🐛 Proposed fix for the sample script
If [ Get ( FoundCount ) = 0 ]
Set Variable [ $result ; Value: JSONSetElement ( "" ; [ "ok" ; False ; JSONBoolean ] ; [ "error" ; "Record not found" ; JSONString ] ) ]
Else
Set Field [ Customers::Photo ; Base64Decode ( $base64 ; $fileName ) ]
+ Set Variable [ $error ; Value: Get ( LastError ) ]
Commit Records/Requests [ With dialog: Off ]
- Set Variable [ $result ; Value: JSONSetElement ( "" ; [ "ok" ; Get ( LastError ) = 0 ; JSONBoolean ] ; [ "error" ; Get ( LastError ) ; JSONNumber ] ) ]
+ If [ $error = 0 ]
+ Set Variable [ $error ; Value: Get ( LastError ) ]
+ End If
+ If [ $error = 0 ]
+ Set Variable [ $result ; Value: JSONSetElement ( "" ; [ "ok" ; True ; JSONBoolean ] ) ]
+ Else
+ Set Variable [ $result ; Value: JSONSetElement ( "" ; [ "ok" ; False ; JSONBoolean ] ; [ "error" ; $error ; JSONNumber ] ) ]
+ End If
End If📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| If [ Get ( FoundCount ) = 0 ] | |
| Set Variable [ $result ; Value: JSONSetElement ( "" ; [ "ok" ; False ; JSONBoolean ] ; [ "error" ; "Record not found" ; JSONString ] ) ] | |
| Else | |
| Set Field [ Customers::Photo ; Base64Decode ( $base64 ; $fileName ) ] | |
| Commit Records/Requests [ With dialog: Off ] | |
| Set Variable [ $result ; Value: JSONSetElement ( "" ; [ "ok" ; Get ( LastError ) = 0 ; JSONBoolean ] ; [ "error" ; Get ( LastError ) ; JSONNumber ] ) ] | |
| End If | |
| If [ Get ( FoundCount ) = 0 ] | |
| Set Variable [ $result ; Value: JSONSetElement ( "" ; [ "ok" ; False ; JSONBoolean ] ; [ "error" ; "Record not found" ; JSONString ] ) ] | |
| Else | |
| Set Field [ Customers::Photo ; Base64Decode ( $base64 ; $fileName ) ] | |
| Set Variable [ $error ; Value: Get ( LastError ) ] | |
| Commit Records/Requests [ With dialog: Off ] | |
| If [ $error = 0 ] | |
| Set Variable [ $error ; Value: Get ( LastError ) ] | |
| End If | |
| If [ $error = 0 ] | |
| Set Variable [ $result ; Value: JSONSetElement ( "" ; [ "ok" ; True ; JSONBoolean ] ) ] | |
| Else | |
| Set Variable [ $result ; Value: JSONSetElement ( "" ; [ "ok" ; False ; JSONBoolean ] ; [ "error" ; $error ; JSONNumber ] ) ] | |
| End If | |
| End If |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/docs/content/docs/webviewer/containers.mdx` around lines 262 - 268,
Update the sample script’s success branch after Set Field so Get ( LastError )
is captured immediately before Commit Records/Requests, and use that captured
value to determine ok and error. Preserve the not-found branch, and emit the
error field only when the captured error is nonzero rather than setting it to 0
on success.
| } | ||
| ``` | ||
|
|
||
| OttoFMS saves the upload under the server's `Documents/otto/{uuid}/` folder and runs your `OttoReceiver` script with an `uploaded_files` array in the payload. Each entry carries `originalname`, `mimetype`, `size`, and `path`. The script uses `path` to pull the file into a container with `Insert File` or `Insert PDF`. Uploads are deleted after 24 hours, so move the file into the solution on receipt. |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🌐 Web query:
OttoFMS webhook file receiver uploaded_files path retention
💡 Result:
In OttoFMS, when files are uploaded via the file receiver endpoint, they are stored in the FileMaker Server's document directory at the following path: fms-server-path/Data/Documents/otto/:channel/:uuid/filename [1]. Regarding file retention, OttoFMS does not provide built-in automated cleanup or expiration policies for files uploaded to this specific directory [1]. Because these files are saved to the server's filesystem, they will remain there indefinitely unless they are manually managed or programmatically deleted by your own processes [1]. It is recommended practice to process these files immediately after the webhook is received—typically by using a script to import the file into a FileMaker container field—and then remove the file from the server's filesystem once the import is complete to prevent the server's storage from filling up [1].
Citations:
🌐 Web query:
site:v3.ottofms.com/docs/otto/working-with-otto/receiving-web-hooks OttoReceiver uploaded_files originalname mimetype size path
💡 Result:
OttoReceiver is a component of Otto, a tool by Proof+Geist designed for Claris FileMaker, used for managing webhooks and file uploads [1]. When files are uploaded via a webhook in Otto, the system automatically adds an uploaded_files array to the webhook payload [1]. This array contains metadata for each file processed, including the following properties [1]: - originalname: The original name of the file as it was uploaded [1]. - mimetype: The MIME type of the uploaded file (e.g., text/markdown) [1]. - size: The size of the file in bytes [1]. - path: The full file system path where the uploaded file is stored on the server [1]. - filename: The name of the file as saved in the destination directory [1]. - fieldname: The name of the form field used to upload the file [1]. - encoding: The encoding type of the file [1]. - destination: The directory path where the file was saved [1]. Developers typically use this information within FileMaker scripts to import the files from the specified path into container fields [1].
Citations:
Correct the OttoFMS file receiver details.
Use Data/Documents/otto/:channel/:uuid/filename for the storage path. Remove the 24-hour deletion claim because OttoFMS does not automatically expire these files. OttoReceiver and the listed uploaded_files fields are valid; the payload also includes filename, fieldname, encoding, and destination.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/docs/content/docs/webviewer/containers.mdx` at line 332, Update the
OttoFMS upload description to use the storage pattern
Data/Documents/otto/:channel/:uuid/filename, remove the claim that uploads are
deleted after 24 hours, and extend the uploaded_files entry fields with
filename, fieldname, encoding, and destination while preserving the valid
OttoReceiver, existing fields, and file-insertion guidance.
| # 1. Parse the envelope | ||
| Set Variable [ $json ; Value: Get ( ScriptParameter ) ] | ||
| Set Variable [ $callback ; Value: JSONGetElement ( $json ; "callback" ) ] | ||
| Set Variable [ $data ; Value: JSONGetElement ( $json ; "data" ) ] | ||
| Set Variable [ $webViewerName ; Value: JSONGetElement ( $callback ; "webViewerName" ) ] | ||
| Set Variable [ $layout ; Value: JSONGetElement ( $data ; "layout" ) ] | ||
| Set Variable [ $recordId ; Value: JSONGetElement ( $data ; "recordId" ) ] | ||
| Set Variable [ $fieldName ; Value: JSONGetElement ( $data ; "containerFieldName" ) ] | ||
| Set Variable [ $fileName ; Value: JSONGetElement ( $data ; "fileName" ) ] | ||
| Set Variable [ $base64 ; Value: JSONGetElement ( $data ; "base64" ) ] | ||
|
|
||
| # 2. Navigate by record ID, in a new window | ||
| Go to List of Records [ List of record IDs: $recordId ; Using layout: $layout ; Show in new window: On ; Animation: None ] | ||
|
|
||
| # 3. Verify, then write | ||
| Set Variable [ $fullFieldName ; Value: Get ( LayoutTableName ) & "::" & $fieldName ] | ||
| Set Field By Name [ $fullFieldName ; Base64Decode ( $base64 ; $fileName ) ] | ||
| Commit Records/Requests [ With dialog: Off ] | ||
|
|
||
| # 4. Close the window, then call back | ||
| Close Window [ Current Window ] | ||
| Set Variable [ $callback ; Value: JSONSetElement ( $callback ; | ||
| [ "result" ; $result ; JSONObject ] ; | ||
| [ "webViewerName" ; $webViewerName ; JSONString ] ) ] | ||
| Perform Script [ Specified: From list ; "SendCallBack" ; Parameter: $callback ] |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
Complete the script flow before using this contract.
The flow never assigns $result. WebViewerAdapter.handleDataApiResponse() requires messages[0].code to equal "0", so a successful write based on this flow still rejects in JavaScript.
Parse and validate modId and repetition. Check navigation, field-write, and commit errors. Build the documented success or failure envelope in $result. Resolve the empty webViewerName fallback before SendCallBack. Route every failure through window cleanup.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/webviewer/specs/container-upload-script.md` around lines 103 - 127,
Complete the script flow around the envelope parsing and callback construction
by extracting and validating modId and repetition, resolving the empty
webViewerName fallback, and assigning $result with code "0" only after
successful navigation, field write, and commit; otherwise build the documented
failure envelope. Ensure every failure path closes the temporary window before
invoking SendCallBack, and preserve the callback contract expected by
WebViewerAdapter.handleDataApiResponse().
- Report unknown outcomes with ContainerUploadTimeoutError - Tighten file-name validation and document retry behavior
- Clarify built-in uploads and custom reads - Streamline FileMaker and browser examples - Document version requirements and container handling
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/docs/content/docs/webviewer/containers.mdx`:
- Around line 30-38: Update the warning text in the containerUpload
prerequisites to replace the inaccurate quoted older-add-on error with the
actual WebViewerAdapter behavior: older add-ons reject with
ContainerUploadTimeoutError after the configured timeout. Keep the
`@proofkit/webviewer` 3.3.0 and FileMaker Pro 22.0 requirements unchanged.
In `@packages/webviewer/specs/container-upload-script.md`:
- Around line 141-145: Update the upload error-handling flow around Set Field By
Name and Commit Records/Requests to capture Get ( LastErrorText ) immediately
after the field update, preserve it through the commit, and replace it with the
commit error text if the commit fails. Pass the captured error message to
PK_error instead of an empty string.
- Around line 123-128: Update the error handling after “Go to List of Records”
to preserve navigation error codes: return 105 with “Layout is missing” when
$error is 105, return 101 with “Record is missing” only when the found set is
empty or the record is missing, and pass through all other nonzero navigation
errors using their actual codes and messages.
- Around line 136-145: Update the upload flow around Set Field By Name to decode
Base64 into a variable before modifying the container. Reject decoded values
equal to “?” or empty by setting result to PK_error with code 500, and only
execute Set Field By Name and Commit Records/Requests for valid decoded data;
preserve the existing post-commit error handling for valid inputs.
- Around line 118-119: Update the repetition parsing near $repetition to reject
invalid values and values greater than 1 before navigation instead of clamping
them with Max ( 1 ; ... ). Preserve repetition 1 for supported requests, and
ensure invalid or unsupported input exits through the script’s existing
rejection path; do not append a repetition qualifier unless implementing full
repetition support in $fullFieldName.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: a1d2182b-74b4-481a-b072-58c5c084d84b
📒 Files selected for processing (5)
.changeset/webviewer-container-upload.mdapps/docs/content/docs/webviewer/containers.mdxpackages/webviewer/specs/container-upload-script.mdpackages/webviewer/src/adapter.tspackages/webviewer/tests/adapter.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- .changeset/webviewer-container-upload.md
- packages/webviewer/tests/adapter.test.ts
- packages/webviewer/src/adapter.ts
- Validate repetition and decode failures - Preserve FileMaker error details - Update container upload docs and tests
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
packages/webviewer/specs/container-upload-script.md (2)
139-142: 🗄️ Data Integrity & Integration | 🟠 MajorMap a no-match navigation result to code 101.
Go to List of Recordscan return401when the requested record ID is missing. The$error ≠ 0branch runs before theFoundCount = 0check, so the script can return401instead of the contract’s101missing-record response.Check
FoundCount = 0for the documented missing-record results before generic error pass-through. Preserve105and other genuine navigation errors. (help.claris.com)Suggested correction
- Else If [ $error ≠ 0 ] - Set Variable [ $result ; Value: PK_error ( $error ; $errorMessage ) ] - Else If [ Get ( FoundCount ) = 0 ] + Else If [ Get ( FoundCount ) = 0 and ( $error = 0 or $error = 401 ) ] Set Variable [ $result ; Value: PK_error ( 101 ; "Record is missing" ) ] + Else If [ $error ≠ 0 ] + Set Variable [ $result ; Value: PK_error ( $error ; $errorMessage ) ]🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/webviewer/specs/container-upload-script.md` around lines 139 - 142, Reorder the result handling so the Get ( FoundCount ) = 0 check maps missing-record navigation results, including error 401, to PK_error ( 101 ; "Record is missing" ) before the generic $error ≠ 0 pass-through. Preserve 105 and other genuine navigation errors by only applying the 101 mapping to the documented no-match result.Source: MCP tools
143-143: 🗄️ Data Integrity & Integration | 🟠 MajorReject malformed
modIdvalues before comparison.
GetAsNumber ( $modId )removes non-numeric characters. A value such as"1abc"can become1and pass the modification check when the current modification count is1.Require a JSON number with the contract’s integer semantics before comparing it. Return an invalid-request error for malformed values. Claris documents this coercion behavior. (help.claris.com)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/webviewer/specs/container-upload-script.md` at line 143, Validate the `modId` extracted by `JSONGetElement` as a contract-compliant JSON integer before the `Get ( RecordModificationCount )` comparison in the upload-script conditional. Reject malformed or non-integer values with the existing invalid-request error path, and only call `GetAsNumber ( $modId )` after validation so strings such as `"1abc"` cannot be accepted.Source: MCP tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/webviewer/specs/container-upload-script.md`:
- Around line 118-120: Update the repetition validation around $repetitionInput,
$repetitionType, and $repetitionIsValid to detect whether the “repetition” key
exists using JSONListKeys instead of treating JSONGetElementType error text as
absence. Accept an omitted key, while requiring present values to have
JSONNumber type and numeric value 1.
---
Duplicate comments:
In `@packages/webviewer/specs/container-upload-script.md`:
- Around line 139-142: Reorder the result handling so the Get ( FoundCount ) = 0
check maps missing-record navigation results, including error 401, to PK_error (
101 ; "Record is missing" ) before the generic $error ≠ 0 pass-through. Preserve
105 and other genuine navigation errors by only applying the 101 mapping to the
documented no-match result.
- Line 143: Validate the `modId` extracted by `JSONGetElement` as a
contract-compliant JSON integer before the `Get ( RecordModificationCount )`
comparison in the upload-script conditional. Reject malformed or non-integer
values with the existing invalid-request error path, and only call `GetAsNumber
( $modId )` after validation so strings such as `"1abc"` cannot be accepted.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 122e7c26-5f2a-4553-aad2-33da62919601
📒 Files selected for processing (4)
apps/docs/content/docs/webviewer/containers.mdxpackages/webviewer/specs/container-upload-script.mdpackages/webviewer/src/adapter.tspackages/webviewer/tests/adapter.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- packages/webviewer/tests/adapter.test.ts
- packages/webviewer/src/adapter.ts
- apps/docs/content/docs/webviewer/containers.mdx
| Set Variable [ $repetitionInput ; Value: JSONGetElement ( $data ; "repetition" ) ] | ||
| Set Variable [ $repetitionType ; Value: JSONGetElementType ( $data ; "repetition" ) ] | ||
| Set Variable [ $repetitionIsValid ; Value: ( IsEmpty ( $repetitionInput ) and IsEmpty ( $repetitionType ) ) or ( $repetitionType = JSONNumber and GetAsNumber ( $repetitionInput ) = 1 ) ] |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- target lines ---'
sed -n '100,135p' packages/webviewer/specs/container-upload-script.md
printf '%s\n' '--- relevant function usage ---'
rg -n -C 3 'JSONGetElementType|JSONListKeys|repetitionIsValid|repetitionPresent|Go to List of Records|modId|Modification' packages/webviewer/specs/container-upload-script.md
printf '%s\n' '--- repository references ---'
rg -n -i 'JSONGetElementType|JSONListKeys|repetition' packages/webviewer/specs --glob '*.md'Repository: proofsh/proofkit
Length of output: 10537
🌐 Web query:
Claris FileMaker Pro JSONGetElementType missing path error text JSONListKeys key presence documentation
💡 Result:
In Claris FileMaker Pro, the behavior of JSON functions when encountering missing or invalid paths is standardized as follows: JSONGetElementType Error Behavior When you use the JSONGetElementType function, if the provided key, index, or path does not exist in the JSON data, the function returns the error text: "? Incorrect key, index, or path" [1][2][3]. JSONListKeys and Key Presence The JSONListKeys function does not explicitly return an error text when a path is missing; instead, if the path is invalid or does not exist, it typically returns an empty string. To determine if a specific key or path exists before performing operations, the best practice is to use JSONGetElementType [4]. By checking the return value of JSONGetElementType against your expected data type (e.g., JSONObject, JSONString), you can programmatically verify the presence of a key [4]. Technical Documentation Notes - Path Notation: The keyOrIndexOrPath parameter supports object names, array indexes, or dot/bracket notation (e.g., "bakery.product.id") [1][5][6]. - Error Handling: If the main JSON input is invalid (i.e., not valid JSON), FileMaker JSON functions will return "?" followed by a specific error message from the JSON parser [4]. - Empty Path: Providing an empty string ("") as the keyOrIndexOrPath parameter targets the root of the JSON structure [7][4][5]. For robust development, always validate the path using JSONGetElementType before relying on subsequent functions like JSONGetElement or JSONListKeys to prevent unexpected results [4].
Citations:
- 1: https://help.claris.com/en/pro-help/content/jsongetelementtype.html
- 2: https://help-origin.claris.com/en/pro-help/content/jsongetelementtype.html
- 3: https://community.claris.com/en/s/question/0D53w00005vSYuyCAG/jsongetelement-fails-to-return-error-when-querying-impossibleillegal-paths-below-strings-case-00585594
- 4: https://help.claris.com/en/pro-help/content/json-functions.html?Highlight=json
- 5: https://help.claris.com/en/pro-help/content/jsonlistkeys.html
- 6: https://help.claris.com/en/pro-help/content/json-functions.html
- 7: https://community.claris.com/en/s/question/0D5Vy000011nJqLKAU/jsongetelementtype-documentation
Handle an omitted repetition as absent.
JSONGetElementType ( $data ; "repetition" ) returns error text for a missing path. Therefore, Line 120 rejects the omitted optional field instead of using the default value.
Detect key presence separately with JSONListKeys. Then accept omission or require JSON number 1.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/webviewer/specs/container-upload-script.md` around lines 118 - 120,
Update the repetition validation around $repetitionInput, $repetitionType, and
$repetitionIsValid to detect whether the “repetition” key exists using
JSONListKeys instead of treating JSONGetElementType error text as absence.
Accept an omitted key, while requiring present values to have JSONNumber type
and numeric value 1.
Source: MCP tools
Summary
containerUploadinWebViewerAdapterwith Base64 encoding and configurable script options.PK_container_uploadFileMaker script contract.Testing
pnpm run cinot run.Summary by CodeRabbit
New Features
Documentation