Skip to content
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

generate typescript definitions #42

Merged
merged 37 commits into from
Jan 30, 2024
Merged

Conversation

jraymakers
Copy link
Contributor

No description provided.

@jraymakers jraymakers changed the title generate typescript definitions WIP generate typescript definitions Jan 8, 2024
@@ -16,7 +16,7 @@
},
"scripts": {
"install": "node-pre-gyp install --fallback-to-build",
"pretest": "node test/support/createdb.js",
"xpretest": "node test/support/createdb.js",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is disabled (by renaming it from "pretest") because it uses the old API.


if isinstance(node.type, pycparser.c_ast.Enum):
self.result += f'auto {name}_enum = Napi::Object::New(env);\n'
self.cpp_result += f'exports.Set(Napi::String::New(env, "{name}"), duckdb_node::PointerHolder<{name}>::Init(env, "{name}")->Value());\n'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I renamed "result" to "cpp_result", since there is now also a "types_result". I haven't changed the generated C++ at all.

self.cpp_result += f'exports.Set(Napi::String::New(env, "{name}"), duckdb_node::PointerHolder<{name}>::Init(env, "{name}")->Value());\n'
self.types_result += f'export class {name} {{}}\n'
self.c_type_to_ts_type[name] = name
self.c_type_to_ts_type[f'{name}*'] = name
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each struct type is exposed to JS as a class that is a variant of PointerHolder. This is true for both direct references to the struct type as well as pointers to that type. I'm representing these as separate classes; the only thing that a TS client can do is "new" them and then pass them around.

# Do these void* types need any corresponding Napi code?
self.types_result += f'export class {name} {{}}\n'
self.c_type_to_ts_type[name] = name
self.c_type_to_ts_type[f'{name}*'] = name
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part handles typedefs like typedef void *duckdb_bind_info;. It's needed because some APIs take or return duckdb_bind_infos.

@@ -59,43 +101,60 @@ def visit_FuncDecl(self, node):

if node.args:
for p in node.args.params:
args.append(typename(p.type))
args.append((p.name, typename(p.type)))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the name of each arg to the args array, so I can generate the TypeScript function signatures with the correct argument names.

return # ??

if 'delete_callback' in name:
print(f'function not handled: {name}')
self.types_result += f'export type {name} = (data: pointer) => void;\n'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed because duckdb_delete_callback_t is used in a couple places.


n_args = len(args)
args.append(name)

fwrap_args = list(map(lambda arg: arg[1], args)) + [name]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than modify args, which I need for the TS generation, I'm creating a copy for the C++ generation. The C++ needs the arg types (not the names), plus the name of the function.

@@ -52,7 +52,7 @@ async function test() {

// we want an incremental AND streaming query result
const pending_result = new duckdb_native.duckdb_pending_result;
await duckdb_native.duckdb_pending_prepared_streaming(prepared_statement, pending_result); // TODO can this fail?
duckdb_native.duckdb_pending_prepared_streaming(prepared_statement, pending_result); // TODO can this fail?
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This await was unnecessary, because this function is not async.

test.js Outdated Show resolved Hide resolved
@jraymakers jraymakers changed the title WIP generate typescript definitions generate typescript definitions Jan 10, 2024
@jraymakers jraymakers marked this pull request as ready for review January 10, 2024 18:43
@@ -4,15 +4,15 @@ const duckdb_native = require('.');
console.log("DuckDB version:", duckdb_native.duckdb_library_version());

function convert_validity(vector, n) {
const res = new Uint8Array(n).fill(true);
const res = Array.from({ length: n }).fill(true);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like this function should return a normal JS array of booleans. This is a more canonical way to do that.

const validity_buf = duckdb_native.copy_buffer(duckdb_native.duckdb_vector_get_validity(vector),
Math.ceil(n / 64) * 8); // this will be null if all rows are valid
if (validity_buf == null) {
return res; // TODO maybe return a singleton so we dont have to allocate?
}
const typed_validity_buf = new BigUint64Array(validity_buf.buffer);
for (let row_idx = 0; row_idx < n; row_idx++) {
res[row_idx] = (typed_validity_buf[Math.floor(row_idx / 64)] & (1n << BigInt(row_idx % 64))) > 0;
res[row_idx] = (typed_validity_buf[Math.floor(row_idx / 64)] & (BigInt(1) << BigInt(row_idx % 64))) > 0;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not all JS targets can handle the newer bigint literal syntax.

#include "duckdb.h"
#include "function_wrappers.hpp"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change happened automatically when I ran clang format.

@hannes hannes merged commit 3d586b3 into duckdb:refactor Jan 30, 2024
3 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants