-
Notifications
You must be signed in to change notification settings - Fork 855
Raw query syntax in typescript #7373
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
base: main
Are you sure you want to change the base?
Conversation
Deploying windmill with
|
| Latest commit: |
6854ab0
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://d01df241.windmill.pages.dev |
| Branch Preview URL: | https://di-ts-datatable-without-temp.windmill.pages.dev |
|
Claude finished @diegoimbert's task in 2m 25s —— View job Code Review: Raw query syntax in typescriptSummaryThis PR adds a new Issues Found🔴 Critical Issues1. Missing Type Exports and Declaration File Updates (typescript-client/sqlUtils.ts:72-74)
🟡 Medium Priority Issues2. Type Safety Concern with TemplateStringsArray Mock (typescript-client/sqlUtils.ts:204)
3. Technical Debt Acknowledged (typescript-client/sqlUtils.ts:201)
Security Considerations✅ No SQL Injection Risks: The implementation correctly:
✅ No Credential Exposure: Database name is properly encapsulated in the args object Performance Considerations✅ Minimal Overhead: The
Code Quality AssessmentStrengths:
Weaknesses:
RecommendationsMust Fix Before Merge:
Should Fix:
Nice to Have:
Testing InstructionsTo test the new raw query syntax feature, navigate to the Windmill app and create a new TypeScript script. In the script editor, test both the existing template literal syntax and the new raw query syntax: Existing syntax (should still work): import * as wmill from 'windmill-client'
const sql = wmill.datatable()
const name = 'test'
await sql`SELECT * FROM users WHERE name = ${name}`.fetch()New raw query syntax: import * as wmill from 'windmill-client'
const sql = wmill.datatable()
await sql.query('SELECT * FROM users WHERE name = $1', 'test').fetch()Test with multiple parameters using positional placeholders ($1, $2, etc.) and verify the results match the template literal approach. Verify that type annotations work correctly (e.g., Tasks Completed:
|
| // This is less than ideal, did that quickly for a client need. | ||
| // TODO: break down the SqlTemplateFunction impl and reuse here properly. | ||
| let arr = Object.assign([sqlString], { raw: [sqlString] }); | ||
| return sql(arr, ...params); |
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.
Type Safety Issue: The Object.assign approach with array literals doesn't properly satisfy the TemplateStringsArray type requirements. While this creates an object that looks like a TemplateStringsArray, it's not actually one.
Potential Issue: The raw property should be read-only according to the TemplateStringsArray interface specification. Consider using a proper type cast or creating a mock that fully satisfies the interface:
const templateStrings = Object.assign([sqlString], {
raw: Object.freeze([sqlString])
}) as unknown as TemplateStringsArray;
return sql(templateStrings, ...params);This ensures immutability of the raw property as per spec.
| sqlString: string, | ||
| ...params: any[] | ||
| ) => { | ||
| // This is less than ideal, did that quickly for a client need. |
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.
Code Quality - TODO Comment: The inline TODO suggests this implementation is temporary and needs refactoring. Before merging:
- Consider whether the technical debt is acceptable for the "client need" mentioned
- If this is a quick fix, create a GitHub issue to track the proper refactoring
- Document the expected behavior and edge cases for future refactoring
Question: What's the timeline for addressing this TODO? Should we create a follow-up issue?
| interface DatatableSqlTemplateFunction extends SqlTemplateFunction { | ||
| query(sql: string, ...params: any[]): SqlStatement; | ||
| } |
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.
Missing Type Export & Declaration File Update: The new DatatableSqlTemplateFunction interface is not:
- Exported from this module (no
exportkeyword) - Updated in the corresponding
.d.tsfile (typescript-client/sqlUtils.d.ts)
Impact:
- TypeScript consumers won't see the
.query()method in their IDE autocomplete - The type declaration file at line 52 still declares
datatablereturningSqlTemplateFunctioninstead ofDatatableSqlTemplateFunction - Users won't get type checking or IntelliSense for the new
query()method
Suggested Fix:
export interface DatatableSqlTemplateFunction extends SqlTemplateFunction {
query(sql: string, ...params: any[]): SqlStatement;
}And update sqlUtils.d.ts line 52:
export declare function datatable(name: string): DatatableSqlTemplateFunction;| export function datatable(name: string = "main"): SqlTemplateFunction { | ||
| return sqlProviderImpl(name, "datatable"); | ||
| export function datatable(name: string = "main"): DatatableSqlTemplateFunction { | ||
| return sqlProviderImpl(name, "datatable") as DatatableSqlTemplateFunction; |
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.
Good: The return type annotation was correctly updated to reflect the new DatatableSqlTemplateFunction interface. However, the cast as DatatableSqlTemplateFunction is necessary because the implementation adds the .query() method conditionally later in sqlProviderImpl().
Consider adding a JSDoc comment explaining the new .query() method usage to the docstring above. For example:
/**
* Create a SQL template function for PostgreSQL/datatable queries
* @param name - Database/datatable name (default: "main")
* @returns SQL template function for building parameterized queries
* @example
* // Template literal syntax
* let sql = wmill.datatable()
* let name = 'Robin'
* let age = 21
* await sql`
* SELECT * FROM friends
* WHERE name = ${name} AND age = ${age}::int
* `.fetch()
*
* @example
* // Raw query syntax (new)
* let sql = wmill.datatable()
* await sql.query('SELECT * FROM friends WHERE name = $1 AND age = $2::int', 'Robin', 21).fetch()
*/
Support for
sql.query('SELECT $1, $2', arg1, arg2).fetchOne()