docs: Convert tutorial markdown code blocks to DocC snippet files#90
docs: Convert tutorial markdown code blocks to DocC snippet files#90
Conversation
Co-authored-by: cbaker6 <8621344+cbaker6@users.noreply.github.com>
…ides Co-authored-by: cbaker6 <8621344+cbaker6@users.noreply.github.com>
|
Important Review skippedBot user detected. To trigger a single review, invoke the You can disable this status message by setting the
Comment |
There was a problem hiding this comment.
Pull request overview
This PR adds comprehensive DocC tutorials for Cloud Code implementation and synchronizes README examples with the working code in routes.swift.
Changes:
- Added two new detailed tutorials: "Cloud Code Functions" and "Cloud Code Triggers" with working examples covering authentication, parameters, error handling, and all trigger types
- Expanded "Configuration" tutorial to cover both environment variable and programmatic approaches with security best practices
- Enhanced "ParseObjects" tutorial with relationships, ParseFile integration, and model sharing patterns
- Updated README code examples to match
routes.swiftimplementation with better formatting and organization
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| ParseServerSwift.tutorial | Reorganized tutorial structure into "Getting Started" and "Cloud Code" chapters with updated tutorial references |
| ParseServerSwift.md | Added "Additional Resources" section with Parse Swift SDK links and Topics organization |
| Configuring Parse Server Swift.tutorial | Rewrote with comprehensive sections on environment variables, webhookKey security, parseServerSwiftConfigure usage, and programmatic configuration |
| Cloud Code.tutorial | Removed generic Cloud Code tutorial (replaced by specific Functions and Triggers tutorials) |
| Cloud Code Triggers.tutorial | New comprehensive tutorial covering all trigger types with working examples from routes.swift |
| Cloud Code Functions.tutorial | New detailed tutorial on Cloud Functions covering parameters, authentication, primary key queries, and error handling |
| Adding ParseObjects.tutorial | Expanded to include ParseCloudUser vs ParseUser distinction, relationships, ParseFile, and model sharing |
| README.md | Synchronized all code examples with routes.swift, added tutorial links, and organized triggers by type |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@copilot please reference the tutorial chapters you added in the table of contents |
|
@copilot please add code snippets in the tutorial to support the text in the tutorial. You should be able to create example code from https://github.com/netreconlab/parse-server-swift/blob/main/Sources/ParseServerSwift/routes.swift Also, please remove any irrelevant commented out code you added in the tutorial text, the commented code should be code snippet examples |
…tutorials Co-authored-by: cbaker6 <8621344+cbaker6@users.noreply.github.com>
Co-authored-by: cbaker6 <8621344+cbaker6@users.noreply.github.com>
…nippet files Co-authored-by: cbaker6 <8621344+cbaker6@users.noreply.github.com>
…ippet files Co-authored-by: cbaker6 <8621344+cbaker6@users.noreply.github.com>
…ippet files Co-authored-by: cbaker6 <8621344+cbaker6@users.noreply.github.com>
@code snippet files Co-authored-by: cbaker6 <8621344+cbaker6@users.noreply.github.com>
Done! All markdown code blocks in @step directives have been converted to @code snippet files across all four tutorials:
The snippet files are properly organized in the Resources directory with appropriate file extensions (.swift, .js, .sh, .txt) and are referenced using @code directives. |
|
@copilot please review the tutorial document and make sure all code snippets align with their respective steps. If needed, feel free to add more code snippets or more steps/text to make the tutorial clearer. When adding code snippets, do not add markdown code blocks, instead everything should be a code snippet |
Co-authored-by: cbaker6 <8621344+cbaker6@users.noreply.github.com>
Completed! I reviewed all four tutorials and added code snippets to every step that was missing them: Added 11 new code snippet files:
All code snippets now properly align with their tutorial step descriptions. No markdown code blocks remain in any @step directive. Commit: 2ea1a81 |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 78 out of 82 changed files in this pull request and generated 18 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Sources/ParseServerSwift/Extensions/ParseHookTrigger+Vapor.swift
Outdated
Show resolved
Hide resolved
Sources/ParseServerSwift/Extensions/ParseHookTrigger+Vapor.swift
Outdated
Show resolved
Hide resolved
Sources/ParseServerSwift/Documentation.docc/Resources/trigger-modify-object.swift
Outdated
Show resolved
Hide resolved
Sources/ParseServerSwift/Documentation.docc/ParseServerSwift.tutorial
Outdated
Show resolved
Hide resolved
Sources/ParseServerSwift/Extensions/ParseHookFunction+Vapor.swift
Outdated
Show resolved
Hide resolved
Sources/ParseServerSwift/Extensions/ParseHookTrigger+Vapor.swift
Outdated
Show resolved
Hide resolved
Sources/ParseServerSwift/Extensions/ParseHookTrigger+Vapor.swift
Outdated
Show resolved
Hide resolved
Sources/ParseServerSwift/Documentation.docc/Resources/shared-package-structure.swift
Show resolved
Hide resolved
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #90 +/- ##
=======================================
Coverage 39.83% 39.83%
=======================================
Files 11 11
Lines 989 989
=======================================
Hits 394 394
Misses 595 595 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 78 out of 82 changed files in this pull request and generated 16 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -0,0 +1,7 @@ | |||
| guard let object = parseRequest.object else { return } | |||
There was a problem hiding this comment.
This snippet uses guard ... else { return } but then returns a ParseHookResponse later. If this snippet is meant to live inside a hook/route handler that returns ParseHookResponse, the else branch should also return a ParseHookResponse (typically an error response) to avoid teaching an invalid pattern.
| - parameter parseServerURLStrings: A set of Parse Server `URL`'s to delete triggers for. | ||
| Defaults to the set of servers added during configuration. | ||
| - throws: An error of `ParseError` type. | ||
| - note: WIll attempt to create triggers on all `parseServerURLStrings`. | ||
| - note: Will attempt to create triggers on all `parseServerURLStrings`. | ||
| Will log an error for each `parseServerURLString` that returns an error. |
There was a problem hiding this comment.
The delete API docs’ note says “Will attempt to create triggers…”, but this overload performs a delete (DELETE). Please update the note (and any similar delete overload docs) to say “delete triggers” to match the behavior.
| let parseRequest = try req.content | ||
| .decode(ParseHookTriggerObjectRequest<User, GameScore>.self) | ||
|
|
||
| req.logger.info("A LiveQuery subscription is being made: \(parseRequest)") |
There was a problem hiding this comment.
The logging call req.logger.info("A LiveQuery subscription is being made: \(parseRequest)") emits the full ParseHookTriggerObjectRequest<User, GameScore> to logs, which is likely to include user authentication data such as a sessionToken. If these logs are compromised, attackers can reuse the tokens to impersonate users or bypass normal access controls. Limit logging to non-sensitive fields (for example, user id, class name, or query parameters) or explicitly redact authentication-related properties from the request before logging.
| let parseRequest = try req.content | ||
| .decode(ParseHookTriggerObjectRequest<User, GameScore>.self) | ||
|
|
||
| req.logger.info("A LiveQuery event occurred: \(parseRequest)") |
There was a problem hiding this comment.
The line req.logger.info("A LiveQuery event occurred: \(parseRequest)") records the entire ParseHookTriggerObjectRequest<User, GameScore> to logs, including embedded user information that may carry a sessionToken. Storing complete request objects in logs exposes authentication tokens and other sensitive fields to anyone with log access, enabling replay or privilege abuse. Instead, log only essential, non-sensitive attributes (for example, event type and objectId) or build a redacted representation of the request before logging.
| let parseRequest = try req.content | ||
| .decode(ParseHookTriggerObjectRequest<User, GameScore>.self) | ||
|
|
||
| req.logger.info("A query is being made: \(parseRequest)") |
There was a problem hiding this comment.
The log statement req.logger.info("A query is being made: \(parseRequest)") records the full ParseHookTriggerObjectRequest<User, GameScore> including the embedded User, which typically contains sensitive fields such as sessionToken. Writing this full request object to logs risks leaking authentication tokens, which can be reused by anyone with log access to impersonate users against Parse Server. Instead, log only non-sensitive attributes (for example, the objectId or query parameters) or construct a sanitized representation of the request before logging.
| let parseRequest = try req.content | ||
| .decode(ParseHookTriggerRequest<User>.self) | ||
|
|
||
| req.logger.info("A ParseFile is being saved: \(parseRequest)") |
There was a problem hiding this comment.
The log statement req.logger.info("A ParseFile is being saved: \(parseRequest)") records the full ParseHookTriggerRequest<User> object, which can include sensitive user information such as sessionToken. If these logs are accessed or leaked, attackers can reuse the tokens to act as the affected users or pivot into other attacks. Only log non-sensitive details (for example, file name or user objectId) or construct a redacted version of the request for logging instead of serializing the whole object.
| let parseRequest = try req.content | ||
| .decode(ParseHookTriggerRequest<User>.self) | ||
|
|
||
| req.logger.info("A ParseFile is being deleted: \(parseRequest)") |
There was a problem hiding this comment.
The call req.logger.info("A ParseFile is being deleted: \(parseRequest)") logs the complete ParseHookTriggerRequest<User> instance, which may contain sensitive authentication data such as the user’s sessionToken. Logging these values to persistent logs can enable session hijacking by anyone with access to the logging backend. Prefer logging only minimal, non-sensitive fields (for example, file id and user objectId) or explicitly redact authentication-related properties before logging the request.
| @@ -0,0 +1 @@ | |||
| req.logger.info("Trigger executed: \(parseRequest)") | |||
There was a problem hiding this comment.
The call to req.logger.info("Trigger executed: \(parseRequest)") logs the entire parseRequest object, which may include sensitive user fields such as sessionToken or other authentication data. If application logs are accessed or exfiltrated, these values can be reused to impersonate users or bypass normal authentication. Limit logging to non-sensitive fields (for example, object identifiers or minimal metadata) or explicitly redact authentication-related properties before logging.
| req.logger.info("File uploaded by user: \(user.objectId ?? "unknown")") | ||
| } | ||
|
|
||
| req.logger.info("A ParseFile is being saved: \(parseRequest)") |
There was a problem hiding this comment.
The statement req.logger.info("A ParseFile is being saved: \(parseRequest)") logs the entire ParseHookTriggerRequest<User> object, which can include sensitive user data such as a sessionToken. Persisting the full request in logs increases the risk that leaked or over-privileged log access can be turned into account takeover by replaying those tokens. Reduce the log scope to non-sensitive fields (for example, objectId or file metadata) or explicitly scrub authentication-related fields before logging.
| let parseRequest = try req.content | ||
| .decode(ParseHookTriggerRequest<User>.self) | ||
|
|
||
| req.logger.info("A LiveQuery connection is being made: \(parseRequest)") |
There was a problem hiding this comment.
The log line req.logger.info("A LiveQuery connection is being made: \(parseRequest)") writes the full ParseHookTriggerRequest<User> to logs, including user details that may contain a sessionToken. Logging these rich request objects makes authentication tokens and other sensitive information available to anyone with log access, enabling replay or impersonation attacks. Log only the minimal, non-sensitive information needed for observability (for example, user objectId or subscription channel) or construct a sanitized version of the request for logging.
Updated the link to the Dockerfile in the README to reflect the latest changes.
Tutorials contained inline markdown code blocks within
@Stepdirectives instead of using DocC's@Codedirective with separate snippet files. All code examples should be in dedicated snippet files following DocC best practices.Changes
Converted all tutorials to use @code snippet files
All four tutorials have been updated to replace inline markdown code blocks with
@Codedirectives referencing snippet files in the Resources directory:Cloud Code Functions Tutorial
hello-function-01.swift,query-with-user-credentials.swift,require-authentication.swift,validate-session.swift,client-call-function.swift,response-types-examples.swift, etc.Cloud Code Triggers Tutorial
trigger-beforesave-01.swift,trigger-beforefind-01.swift,trigger-afterlogin.swift,trigger-livequery-beforeconnect.swift,trigger-check-headers.swift,trigger-types-overview.swift,trigger-bool-return-types.swift,trigger-performance-tips.swift, etc.Adding ParseObjects Tutorial
gamescore-with-merge.swift,user-with-relations.swift,profile-with-files.swift,post-with-pointer.swift,parseobject-required-properties.swift,gamescore-many-properties.swift,user-match-schema.swift,shared-package-structure.swift, etc.Configuring Parse Server Swift Tutorial
entrypoint-config.swift,parse-server-config.js,start-server.sh,env-config.txt,sdk-manual-config.swift,env-config-explained.txt,configure-function-steps.swift, etc.Enhanced tutorial clarity
Added code snippets to all informational and explanatory steps that previously only had text:
ParseHookResponsetypesAdditional improvements
FooParameters.swiftandUser.swiftsnippet files added to Resources@Codedirectives already existedroutes.swiftResult
@Codedirectives following DocC best practices💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.