tranfi 0.0.2 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +395 -0
- package/app/assets/index-6quYZ5Ap.css +5 -0
- package/app/assets/index-pDFMluyz.js +160 -0
- package/app/assets/materialdesignicons-webfont-B7mPwVP_.ttf +0 -0
- package/app/assets/materialdesignicons-webfont-CSr8KVlo.eot +0 -0
- package/app/assets/materialdesignicons-webfont-Dp5v-WZN.woff2 +0 -0
- package/app/assets/materialdesignicons-webfont-PXm3-2wK.woff +0 -0
- package/app/index.html +13 -0
- package/binding.gyp +69 -0
- package/csrc/arena.c +91 -0
- package/csrc/batch.c +229 -0
- package/csrc/buffer.c +78 -0
- package/csrc/cJSON.c +3143 -0
- package/csrc/cJSON.h +300 -0
- package/csrc/codec_csv.c +1058 -0
- package/csrc/codec_jsonl.c +374 -0
- package/csrc/codec_table.c +218 -0
- package/csrc/codec_text.c +229 -0
- package/csrc/compiler.c +102 -0
- package/csrc/date_utils.h +94 -0
- package/csrc/dsl.c +1180 -0
- package/csrc/dsl.h +22 -0
- package/csrc/expr.c +1245 -0
- package/csrc/expr.h +56 -0
- package/csrc/internal.h +250 -0
- package/csrc/ir.c +119 -0
- package/csrc/ir.h +167 -0
- package/csrc/ir_schema.c +60 -0
- package/csrc/ir_serialize.c +104 -0
- package/csrc/ir_sql.c +1211 -0
- package/csrc/ir_validate.c +120 -0
- package/csrc/main.c +392 -0
- package/csrc/op_acf.c +133 -0
- package/csrc/op_anomaly.c +120 -0
- package/csrc/op_bin.c +109 -0
- package/csrc/op_cast.c +195 -0
- package/csrc/op_clip.c +88 -0
- package/csrc/op_date_trunc.c +181 -0
- package/csrc/op_datetime.c +212 -0
- package/csrc/op_derive.c +248 -0
- package/csrc/op_diff.c +134 -0
- package/csrc/op_ewma.c +103 -0
- package/csrc/op_explode.c +108 -0
- package/csrc/op_fill_down.c +163 -0
- package/csrc/op_fill_null.c +123 -0
- package/csrc/op_filter.c +132 -0
- package/csrc/op_frequency.c +193 -0
- package/csrc/op_grep.c +163 -0
- package/csrc/op_group_agg.c +285 -0
- package/csrc/op_hash.c +126 -0
- package/csrc/op_head.c +149 -0
- package/csrc/op_interpolate.c +239 -0
- package/csrc/op_join.c +384 -0
- package/csrc/op_label_encode.c +144 -0
- package/csrc/op_lead.c +190 -0
- package/csrc/op_normalize.c +226 -0
- package/csrc/op_onehot.c +185 -0
- package/csrc/op_pivot.c +370 -0
- package/csrc/op_registry.c +1148 -0
- package/csrc/op_rename.c +138 -0
- package/csrc/op_replace.c +202 -0
- package/csrc/op_sample.c +101 -0
- package/csrc/op_select.c +140 -0
- package/csrc/op_skip.c +152 -0
- package/csrc/op_sort.c +273 -0
- package/csrc/op_split.c +114 -0
- package/csrc/op_split_data.c +87 -0
- package/csrc/op_stack.c +315 -0
- package/csrc/op_stats.c +779 -0
- package/csrc/op_step.c +171 -0
- package/csrc/op_tail.c +96 -0
- package/csrc/op_top.c +150 -0
- package/csrc/op_trim.c +109 -0
- package/csrc/op_unique.c +300 -0
- package/csrc/op_unpivot.c +159 -0
- package/csrc/op_validate.c +71 -0
- package/csrc/op_window.c +150 -0
- package/csrc/pipeline.c +315 -0
- package/csrc/plan.c +206 -0
- package/csrc/recipes.c +102 -0
- package/csrc/recipes.h +27 -0
- package/csrc/report.c +463 -0
- package/csrc/report.h +22 -0
- package/csrc/tranfi.h +123 -0
- package/csrc/wasm_api.c +157 -0
- package/napi_api.c +326 -0
- package/package.json +46 -57
- package/src/cli.js +193 -0
- package/src/engines/duckdb.js +109 -0
- package/src/index.js +306 -0
- package/src/native.js +22 -0
- package/src/pipeline.js +286 -0
- package/src/server.js +277 -0
- package/src/wasm.js +19 -0
- package/wasm/index.js +244 -0
- package/wasm/package.json +1 -0
- package/wasm/tranfi_core.js +0 -0
- package/LICENSE +0 -21
- package/dist/bundle.js +0 -1
- package/index.html +0 -18
- package/src/app.css +0 -169
- package/src/app.js +0 -203
- package/src/app.vue +0 -250
- package/src/bulma-input.vue +0 -110
- package/src/common-inputs.js +0 -28
- package/src/main.js +0 -20
- package/src/transforms.js +0 -166
- package/webpack.config.js +0 -108
package/csrc/wasm_api.c
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* wasm_api.c — Emscripten WASM exports for Tranfi.
|
|
3
|
+
*
|
|
4
|
+
* Handle-based API: JS gets integer handles instead of raw pointers.
|
|
5
|
+
* Same pattern as statsim/compiler.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#ifdef __EMSCRIPTEN__
|
|
9
|
+
#include <emscripten.h>
|
|
10
|
+
#endif
|
|
11
|
+
|
|
12
|
+
#include "tranfi.h"
|
|
13
|
+
#include "dsl.h"
|
|
14
|
+
#include "recipes.h"
|
|
15
|
+
#include <stdlib.h>
|
|
16
|
+
#include <string.h>
|
|
17
|
+
|
|
18
|
+
/* Handle map: slot index → tf_pipeline* */
|
|
19
|
+
#define MAX_HANDLES 256
|
|
20
|
+
static tf_pipeline *handles[MAX_HANDLES] = {0};
|
|
21
|
+
|
|
22
|
+
static int alloc_handle(tf_pipeline *p) {
|
|
23
|
+
for (int i = 1; i < MAX_HANDLES; i++) {
|
|
24
|
+
if (!handles[i]) {
|
|
25
|
+
handles[i] = p;
|
|
26
|
+
return i;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return -1; /* no free slots */
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static tf_pipeline *get_handle(int h) {
|
|
33
|
+
if (h <= 0 || h >= MAX_HANDLES) return NULL;
|
|
34
|
+
return handles[h];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
#ifdef __EMSCRIPTEN__
|
|
38
|
+
#define EXPORT EMSCRIPTEN_KEEPALIVE
|
|
39
|
+
#else
|
|
40
|
+
#define EXPORT
|
|
41
|
+
#endif
|
|
42
|
+
|
|
43
|
+
EXPORT
|
|
44
|
+
int wasm_pipeline_create(const char *json, int len) {
|
|
45
|
+
tf_pipeline *p = tf_pipeline_create(json, (size_t)len);
|
|
46
|
+
if (!p) return -1;
|
|
47
|
+
int h = alloc_handle(p);
|
|
48
|
+
if (h < 0) {
|
|
49
|
+
tf_pipeline_free(p);
|
|
50
|
+
return -1;
|
|
51
|
+
}
|
|
52
|
+
return h;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
EXPORT
|
|
56
|
+
int wasm_pipeline_push(int handle, const uint8_t *data, int len) {
|
|
57
|
+
tf_pipeline *p = get_handle(handle);
|
|
58
|
+
if (!p) return -1;
|
|
59
|
+
return tf_pipeline_push(p, data, (size_t)len);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
EXPORT
|
|
63
|
+
int wasm_pipeline_finish(int handle) {
|
|
64
|
+
tf_pipeline *p = get_handle(handle);
|
|
65
|
+
if (!p) return -1;
|
|
66
|
+
return tf_pipeline_finish(p);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
EXPORT
|
|
70
|
+
int wasm_pipeline_pull(int handle, int channel, uint8_t *buf, int buf_len) {
|
|
71
|
+
tf_pipeline *p = get_handle(handle);
|
|
72
|
+
if (!p) return 0;
|
|
73
|
+
return (int)tf_pipeline_pull(p, channel, buf, (size_t)buf_len);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
EXPORT
|
|
77
|
+
const char *wasm_pipeline_error(int handle) {
|
|
78
|
+
tf_pipeline *p = get_handle(handle);
|
|
79
|
+
if (!p) return tf_last_error();
|
|
80
|
+
const char *err = tf_pipeline_error(p);
|
|
81
|
+
return err ? err : tf_last_error();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
EXPORT
|
|
85
|
+
void wasm_pipeline_free(int handle) {
|
|
86
|
+
tf_pipeline *p = get_handle(handle);
|
|
87
|
+
if (p) {
|
|
88
|
+
tf_pipeline_free(p);
|
|
89
|
+
handles[handle] = NULL;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/*
|
|
94
|
+
* wasm_compile_dsl — parse DSL string, return plan JSON.
|
|
95
|
+
*
|
|
96
|
+
* Returns heap-allocated JSON string (caller must free), or NULL on error.
|
|
97
|
+
* On error, wasm_pipeline_error(-1) returns the message.
|
|
98
|
+
*/
|
|
99
|
+
EXPORT
|
|
100
|
+
char *wasm_compile_dsl(const char *dsl, int len) {
|
|
101
|
+
char *error = NULL;
|
|
102
|
+
tf_ir_plan *plan = tf_dsl_parse(dsl, (size_t)len, &error);
|
|
103
|
+
if (!plan) {
|
|
104
|
+
/* Store error so JS can retrieve it via wasm_pipeline_error(-1) */
|
|
105
|
+
(void)error; /* error accessible via tf_last_error() */
|
|
106
|
+
free(error);
|
|
107
|
+
return NULL;
|
|
108
|
+
}
|
|
109
|
+
char *json = tf_ir_plan_to_json(plan);
|
|
110
|
+
tf_ir_plan_destroy(plan);
|
|
111
|
+
return json;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/*
|
|
115
|
+
* wasm_compile_to_sql — compile DSL to SQL query string.
|
|
116
|
+
*
|
|
117
|
+
* Returns heap-allocated SQL string (caller must free), or NULL on error.
|
|
118
|
+
*/
|
|
119
|
+
EXPORT
|
|
120
|
+
char *wasm_compile_to_sql(const char *dsl, int len) {
|
|
121
|
+
char *error = NULL;
|
|
122
|
+
char *sql = tf_compile_to_sql(dsl, (size_t)len, &error);
|
|
123
|
+
free(error);
|
|
124
|
+
return sql;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
EXPORT
|
|
128
|
+
const char *wasm_version(void) {
|
|
129
|
+
return tf_version();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/* ---- Recipe API ---- */
|
|
133
|
+
|
|
134
|
+
EXPORT
|
|
135
|
+
int wasm_recipe_count(void) {
|
|
136
|
+
return (int)tf_recipe_count();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
EXPORT
|
|
140
|
+
const char *wasm_recipe_name(int index) {
|
|
141
|
+
return tf_recipe_name((size_t)index);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
EXPORT
|
|
145
|
+
const char *wasm_recipe_dsl(int index) {
|
|
146
|
+
return tf_recipe_dsl((size_t)index);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
EXPORT
|
|
150
|
+
const char *wasm_recipe_description(int index) {
|
|
151
|
+
return tf_recipe_description((size_t)index);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
EXPORT
|
|
155
|
+
const char *wasm_recipe_find_dsl(const char *name) {
|
|
156
|
+
return tf_recipe_find_dsl(name);
|
|
157
|
+
}
|
package/napi_api.c
ADDED
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* napi_api.c — Node.js N-API addon for Tranfi.
|
|
3
|
+
*
|
|
4
|
+
* Exposes the C pipeline API as native Node functions.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
#include <node_api.h>
|
|
8
|
+
#include "tranfi.h"
|
|
9
|
+
#include "dsl.h"
|
|
10
|
+
#include "recipes.h"
|
|
11
|
+
#include <stdlib.h>
|
|
12
|
+
#include <string.h>
|
|
13
|
+
|
|
14
|
+
#define NAPI_CALL(env, call) \
|
|
15
|
+
do { \
|
|
16
|
+
napi_status status = (call); \
|
|
17
|
+
if (status != napi_ok) { \
|
|
18
|
+
napi_throw_error(env, NULL, "N-API call failed"); \
|
|
19
|
+
return NULL; \
|
|
20
|
+
} \
|
|
21
|
+
} while (0)
|
|
22
|
+
|
|
23
|
+
/*ాcreate_pipeline(planJson: string) → External */
|
|
24
|
+
static napi_value napi_create_pipeline(napi_env env, napi_callback_info info) {
|
|
25
|
+
size_t argc = 1;
|
|
26
|
+
napi_value argv[1];
|
|
27
|
+
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
|
|
28
|
+
|
|
29
|
+
if (argc < 1) {
|
|
30
|
+
napi_throw_error(env, NULL, "createPipeline requires plan JSON string");
|
|
31
|
+
return NULL;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
size_t str_len;
|
|
35
|
+
NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], NULL, 0, &str_len));
|
|
36
|
+
char *json = malloc(str_len + 1);
|
|
37
|
+
NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], json, str_len + 1, &str_len));
|
|
38
|
+
|
|
39
|
+
tf_pipeline *p = tf_pipeline_create(json, str_len);
|
|
40
|
+
free(json);
|
|
41
|
+
|
|
42
|
+
if (!p) {
|
|
43
|
+
const char *err = tf_last_error();
|
|
44
|
+
napi_throw_error(env, NULL, err ? err : "failed to create pipeline");
|
|
45
|
+
return NULL;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
napi_value external;
|
|
49
|
+
NAPI_CALL(env, napi_create_external(env, p, NULL, NULL, &external));
|
|
50
|
+
return external;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* push(pipeline: External, data: Buffer) → void */
|
|
54
|
+
static napi_value napi_push(napi_env env, napi_callback_info info) {
|
|
55
|
+
size_t argc = 2;
|
|
56
|
+
napi_value argv[2];
|
|
57
|
+
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
|
|
58
|
+
|
|
59
|
+
tf_pipeline *p;
|
|
60
|
+
NAPI_CALL(env, napi_get_value_external(env, argv[0], (void **)&p));
|
|
61
|
+
|
|
62
|
+
uint8_t *data;
|
|
63
|
+
size_t len;
|
|
64
|
+
NAPI_CALL(env, napi_get_buffer_info(env, argv[1], (void **)&data, &len));
|
|
65
|
+
|
|
66
|
+
int rc = tf_pipeline_push(p, data, len);
|
|
67
|
+
if (rc != 0) {
|
|
68
|
+
const char *err = tf_pipeline_error(p);
|
|
69
|
+
napi_throw_error(env, NULL, err ? err : "push failed");
|
|
70
|
+
}
|
|
71
|
+
return NULL;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* finish(pipeline: External) → void */
|
|
75
|
+
static napi_value napi_finish(napi_env env, napi_callback_info info) {
|
|
76
|
+
size_t argc = 1;
|
|
77
|
+
napi_value argv[1];
|
|
78
|
+
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
|
|
79
|
+
|
|
80
|
+
tf_pipeline *p;
|
|
81
|
+
NAPI_CALL(env, napi_get_value_external(env, argv[0], (void **)&p));
|
|
82
|
+
|
|
83
|
+
int rc = tf_pipeline_finish(p);
|
|
84
|
+
if (rc != 0) {
|
|
85
|
+
const char *err = tf_pipeline_error(p);
|
|
86
|
+
napi_throw_error(env, NULL, err ? err : "finish failed");
|
|
87
|
+
}
|
|
88
|
+
return NULL;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/* pull(pipeline: External, channel: number) → Buffer */
|
|
92
|
+
static napi_value napi_pull(napi_env env, napi_callback_info info) {
|
|
93
|
+
size_t argc = 2;
|
|
94
|
+
napi_value argv[2];
|
|
95
|
+
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
|
|
96
|
+
|
|
97
|
+
tf_pipeline *p;
|
|
98
|
+
NAPI_CALL(env, napi_get_value_external(env, argv[0], (void **)&p));
|
|
99
|
+
|
|
100
|
+
int32_t channel;
|
|
101
|
+
NAPI_CALL(env, napi_get_value_int32(env, argv[1], &channel));
|
|
102
|
+
|
|
103
|
+
/* Pull all available data */
|
|
104
|
+
size_t total = 0;
|
|
105
|
+
size_t cap = 65536;
|
|
106
|
+
uint8_t *result = malloc(cap);
|
|
107
|
+
uint8_t buf[65536];
|
|
108
|
+
|
|
109
|
+
for (;;) {
|
|
110
|
+
size_t n = tf_pipeline_pull(p, channel, buf, sizeof(buf));
|
|
111
|
+
if (n == 0) break;
|
|
112
|
+
if (total + n > cap) {
|
|
113
|
+
while (cap < total + n) cap *= 2;
|
|
114
|
+
result = realloc(result, cap);
|
|
115
|
+
}
|
|
116
|
+
memcpy(result + total, buf, n);
|
|
117
|
+
total += n;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
napi_value buffer;
|
|
121
|
+
void *buf_data;
|
|
122
|
+
NAPI_CALL(env, napi_create_buffer_copy(env, total, result, &buf_data, &buffer));
|
|
123
|
+
free(result);
|
|
124
|
+
return buffer;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/* free(pipeline: External) → void */
|
|
128
|
+
static napi_value napi_free_pipeline(napi_env env, napi_callback_info info) {
|
|
129
|
+
size_t argc = 1;
|
|
130
|
+
napi_value argv[1];
|
|
131
|
+
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
|
|
132
|
+
|
|
133
|
+
tf_pipeline *p;
|
|
134
|
+
NAPI_CALL(env, napi_get_value_external(env, argv[0], (void **)&p));
|
|
135
|
+
|
|
136
|
+
tf_pipeline_free(p);
|
|
137
|
+
return NULL;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/* version() → string */
|
|
141
|
+
static napi_value napi_tranfi_version(napi_env env, napi_callback_info info) {
|
|
142
|
+
(void)info;
|
|
143
|
+
const char *v = tf_version();
|
|
144
|
+
napi_value result;
|
|
145
|
+
NAPI_CALL(env, napi_create_string_utf8(env, v, strlen(v), &result));
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/* error(pipeline: External) → string | null */
|
|
150
|
+
static napi_value napi_tranfi_error(napi_env env, napi_callback_info info) {
|
|
151
|
+
size_t argc = 1;
|
|
152
|
+
napi_value argv[1];
|
|
153
|
+
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
|
|
154
|
+
|
|
155
|
+
tf_pipeline *p;
|
|
156
|
+
NAPI_CALL(env, napi_get_value_external(env, argv[0], (void **)&p));
|
|
157
|
+
|
|
158
|
+
const char *err = tf_pipeline_error(p);
|
|
159
|
+
if (!err) {
|
|
160
|
+
napi_value null_val;
|
|
161
|
+
napi_get_null(env, &null_val);
|
|
162
|
+
return null_val;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
napi_value result;
|
|
166
|
+
NAPI_CALL(env, napi_create_string_utf8(env, err, strlen(err), &result));
|
|
167
|
+
return result;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/* compileDsl(dslString: string) → string (plan JSON) */
|
|
171
|
+
static napi_value napi_compile_dsl(napi_env env, napi_callback_info info) {
|
|
172
|
+
size_t argc = 1;
|
|
173
|
+
napi_value argv[1];
|
|
174
|
+
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
|
|
175
|
+
|
|
176
|
+
if (argc < 1) {
|
|
177
|
+
napi_throw_error(env, NULL, "compileDsl requires DSL string");
|
|
178
|
+
return NULL;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
size_t str_len;
|
|
182
|
+
NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], NULL, 0, &str_len));
|
|
183
|
+
char *dsl = malloc(str_len + 1);
|
|
184
|
+
NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], dsl, str_len + 1, &str_len));
|
|
185
|
+
|
|
186
|
+
char *error = NULL;
|
|
187
|
+
tf_ir_plan *plan = tf_dsl_parse(dsl, str_len, &error);
|
|
188
|
+
free(dsl);
|
|
189
|
+
|
|
190
|
+
if (!plan) {
|
|
191
|
+
napi_throw_error(env, NULL, error ? error : "DSL parse failed");
|
|
192
|
+
free(error);
|
|
193
|
+
return NULL;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
char *json = tf_ir_plan_to_json(plan);
|
|
197
|
+
tf_ir_plan_destroy(plan);
|
|
198
|
+
|
|
199
|
+
napi_value result;
|
|
200
|
+
NAPI_CALL(env, napi_create_string_utf8(env, json, strlen(json), &result));
|
|
201
|
+
free(json);
|
|
202
|
+
return result;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/* compileToSql(dslString: string) → string (SQL query) */
|
|
206
|
+
static napi_value napi_compile_to_sql(napi_env env, napi_callback_info info) {
|
|
207
|
+
size_t argc = 1;
|
|
208
|
+
napi_value argv[1];
|
|
209
|
+
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
|
|
210
|
+
|
|
211
|
+
if (argc < 1) {
|
|
212
|
+
napi_throw_error(env, NULL, "compileToSql requires DSL string");
|
|
213
|
+
return NULL;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
size_t str_len;
|
|
217
|
+
NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], NULL, 0, &str_len));
|
|
218
|
+
char *dsl = malloc(str_len + 1);
|
|
219
|
+
NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], dsl, str_len + 1, &str_len));
|
|
220
|
+
|
|
221
|
+
char *error = NULL;
|
|
222
|
+
char *sql = tf_compile_to_sql(dsl, str_len, &error);
|
|
223
|
+
free(dsl);
|
|
224
|
+
|
|
225
|
+
if (!sql) {
|
|
226
|
+
napi_throw_error(env, NULL, error ? error : "SQL compilation failed");
|
|
227
|
+
free(error);
|
|
228
|
+
return NULL;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
napi_value result;
|
|
232
|
+
NAPI_CALL(env, napi_create_string_utf8(env, sql, strlen(sql), &result));
|
|
233
|
+
tf_string_free(sql);
|
|
234
|
+
return result;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/* recipeCount() → number */
|
|
238
|
+
static napi_value napi_recipe_count(napi_env env, napi_callback_info info) {
|
|
239
|
+
(void)info;
|
|
240
|
+
napi_value result;
|
|
241
|
+
NAPI_CALL(env, napi_create_uint32(env, (uint32_t)tf_recipe_count(), &result));
|
|
242
|
+
return result;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/* recipeName(index: number) → string | null */
|
|
246
|
+
static napi_value napi_recipe_name(napi_env env, napi_callback_info info) {
|
|
247
|
+
size_t argc = 1;
|
|
248
|
+
napi_value argv[1];
|
|
249
|
+
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
|
|
250
|
+
uint32_t index;
|
|
251
|
+
NAPI_CALL(env, napi_get_value_uint32(env, argv[0], &index));
|
|
252
|
+
const char *s = tf_recipe_name(index);
|
|
253
|
+
if (!s) { napi_value n; napi_get_null(env, &n); return n; }
|
|
254
|
+
napi_value result;
|
|
255
|
+
NAPI_CALL(env, napi_create_string_utf8(env, s, strlen(s), &result));
|
|
256
|
+
return result;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/* recipeDsl(index: number) → string | null */
|
|
260
|
+
static napi_value napi_recipe_dsl(napi_env env, napi_callback_info info) {
|
|
261
|
+
size_t argc = 1;
|
|
262
|
+
napi_value argv[1];
|
|
263
|
+
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
|
|
264
|
+
uint32_t index;
|
|
265
|
+
NAPI_CALL(env, napi_get_value_uint32(env, argv[0], &index));
|
|
266
|
+
const char *s = tf_recipe_dsl(index);
|
|
267
|
+
if (!s) { napi_value n; napi_get_null(env, &n); return n; }
|
|
268
|
+
napi_value result;
|
|
269
|
+
NAPI_CALL(env, napi_create_string_utf8(env, s, strlen(s), &result));
|
|
270
|
+
return result;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/* recipeDescription(index: number) → string | null */
|
|
274
|
+
static napi_value napi_recipe_description(napi_env env, napi_callback_info info) {
|
|
275
|
+
size_t argc = 1;
|
|
276
|
+
napi_value argv[1];
|
|
277
|
+
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
|
|
278
|
+
uint32_t index;
|
|
279
|
+
NAPI_CALL(env, napi_get_value_uint32(env, argv[0], &index));
|
|
280
|
+
const char *s = tf_recipe_description(index);
|
|
281
|
+
if (!s) { napi_value n; napi_get_null(env, &n); return n; }
|
|
282
|
+
napi_value result;
|
|
283
|
+
NAPI_CALL(env, napi_create_string_utf8(env, s, strlen(s), &result));
|
|
284
|
+
return result;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/* recipeFindDsl(name: string) → string | null */
|
|
288
|
+
static napi_value napi_recipe_find_dsl(napi_env env, napi_callback_info info) {
|
|
289
|
+
size_t argc = 1;
|
|
290
|
+
napi_value argv[1];
|
|
291
|
+
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
|
|
292
|
+
size_t str_len;
|
|
293
|
+
NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], NULL, 0, &str_len));
|
|
294
|
+
char *name = malloc(str_len + 1);
|
|
295
|
+
NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], name, str_len + 1, &str_len));
|
|
296
|
+
const char *dsl = tf_recipe_find_dsl(name);
|
|
297
|
+
free(name);
|
|
298
|
+
if (!dsl) { napi_value n; napi_get_null(env, &n); return n; }
|
|
299
|
+
napi_value result;
|
|
300
|
+
NAPI_CALL(env, napi_create_string_utf8(env, dsl, strlen(dsl), &result));
|
|
301
|
+
return result;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/* Module init */
|
|
305
|
+
static napi_value init(napi_env env, napi_value exports) {
|
|
306
|
+
napi_property_descriptor props[] = {
|
|
307
|
+
{"createPipeline", NULL, napi_create_pipeline, NULL, NULL, NULL, napi_default, NULL},
|
|
308
|
+
{"push", NULL, napi_push, NULL, NULL, NULL, napi_default, NULL},
|
|
309
|
+
{"finish", NULL, napi_finish, NULL, NULL, NULL, napi_default, NULL},
|
|
310
|
+
{"pull", NULL, napi_pull, NULL, NULL, NULL, napi_default, NULL},
|
|
311
|
+
{"free", NULL, napi_free_pipeline, NULL, NULL, NULL, napi_default, NULL},
|
|
312
|
+
{"version", NULL, napi_tranfi_version, NULL, NULL, NULL, napi_default, NULL},
|
|
313
|
+
{"error", NULL, napi_tranfi_error, NULL, NULL, NULL, napi_default, NULL},
|
|
314
|
+
{"compileDsl", NULL, napi_compile_dsl, NULL, NULL, NULL, napi_default, NULL},
|
|
315
|
+
{"compileToSql", NULL, napi_compile_to_sql, NULL, NULL, NULL, napi_default, NULL},
|
|
316
|
+
{"recipeCount", NULL, napi_recipe_count, NULL, NULL, NULL, napi_default, NULL},
|
|
317
|
+
{"recipeName", NULL, napi_recipe_name, NULL, NULL, NULL, napi_default, NULL},
|
|
318
|
+
{"recipeDsl", NULL, napi_recipe_dsl, NULL, NULL, NULL, napi_default, NULL},
|
|
319
|
+
{"recipeDescription", NULL, napi_recipe_description, NULL, NULL, NULL, napi_default, NULL},
|
|
320
|
+
{"recipeFindDsl", NULL, napi_recipe_find_dsl, NULL, NULL, NULL, napi_default, NULL},
|
|
321
|
+
};
|
|
322
|
+
NAPI_CALL(env, napi_define_properties(env, exports, 14, props));
|
|
323
|
+
return exports;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
NAPI_MODULE(NODE_GYP_MODULE_NAME, init)
|
package/package.json
CHANGED
|
@@ -1,68 +1,57 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tranfi",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "Streaming ETL language + runtime",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"tranfi": "src/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
".": "./src/index.js",
|
|
12
|
+
"./wasm": "./wasm/index.js"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"src/",
|
|
16
|
+
"wasm/",
|
|
17
|
+
"csrc/",
|
|
18
|
+
"app/",
|
|
19
|
+
"napi_api.c",
|
|
20
|
+
"binding.gyp",
|
|
21
|
+
"README.md"
|
|
22
|
+
],
|
|
6
23
|
"scripts": {
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
|
|
12
|
-
|
|
24
|
+
"prepack": "rm -rf csrc && mkdir -p csrc && cp ../src/*.c ../src/*.h csrc/ && rm -rf app && cp -r ../app/dist app && rm -rf app/wasm app/lib",
|
|
25
|
+
"install": "node-gyp rebuild 2>/dev/null || true",
|
|
26
|
+
"build:native": "rm -rf csrc && mkdir -p csrc && cp ../src/*.c ../src/*.h csrc/ && node-gyp rebuild",
|
|
27
|
+
"test": "node ../test/test_node.js"
|
|
28
|
+
},
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"duckdb": ">=1.0.0",
|
|
31
|
+
"@duckdb/duckdb-wasm": ">=1.0.0"
|
|
13
32
|
},
|
|
14
|
-
"
|
|
33
|
+
"peerDependenciesMeta": {
|
|
34
|
+
"duckdb": {
|
|
35
|
+
"optional": true
|
|
36
|
+
},
|
|
37
|
+
"@duckdb/duckdb-wasm": {
|
|
38
|
+
"optional": true
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"keywords": [
|
|
42
|
+
"etl",
|
|
43
|
+
"csv",
|
|
44
|
+
"streaming",
|
|
45
|
+
"data",
|
|
46
|
+
"pipeline",
|
|
47
|
+
"transform"
|
|
48
|
+
],
|
|
15
49
|
"license": "MIT",
|
|
16
50
|
"repository": {
|
|
17
51
|
"type": "git",
|
|
18
|
-
"url": "
|
|
19
|
-
},
|
|
20
|
-
"dependencies": {
|
|
21
|
-
"@jseeio/jsee": "^0.2.8",
|
|
22
|
-
"buffer": "^6.0.3",
|
|
23
|
-
"bulma": "^0.9.3",
|
|
24
|
-
"csv-parse": "^4.16.3",
|
|
25
|
-
"element-plus": "^1.2.0-beta.6",
|
|
26
|
-
"equal-vue": "^0.79.3",
|
|
27
|
-
"file-saver": "^2.0.2",
|
|
28
|
-
"filestream": "^5.0.0",
|
|
29
|
-
"filtrex": "^2.2.3",
|
|
30
|
-
"JSONStream": "^1.3.5",
|
|
31
|
-
"notyf": "^3.10.0",
|
|
32
|
-
"process": "^0.11.10",
|
|
33
|
-
"stream-browserify": "^3.0.0",
|
|
34
|
-
"stream-http": "^3.2.0",
|
|
35
|
-
"through2": "^4.0.2",
|
|
36
|
-
"unzip-stream": "^0.3.1",
|
|
37
|
-
"url": "^0.11.0",
|
|
38
|
-
"vue": "^3.2.23",
|
|
39
|
-
"vue-style-loader": "^4.1.3",
|
|
40
|
-
"vue3-json-viewer": "^1.0.4",
|
|
41
|
-
"vuedraggable": "^4.1.0",
|
|
42
|
-
"vuex": "^4.0.2"
|
|
52
|
+
"url": "https://github.com/tranfi/tranfi"
|
|
43
53
|
},
|
|
44
54
|
"devDependencies": {
|
|
45
|
-
"
|
|
46
|
-
"@babel/plugin-transform-runtime": "^7.4.4",
|
|
47
|
-
"@babel/preset-env": "^7.16.5",
|
|
48
|
-
"babel-loader": "^8.2.3",
|
|
49
|
-
"css-loader": "^6.5.1",
|
|
50
|
-
"http-server": "^14.0.0",
|
|
51
|
-
"jest": "^27.4.5",
|
|
52
|
-
"jest-puppeteer": "^6.0.3",
|
|
53
|
-
"node-sass": "^7.0.0",
|
|
54
|
-
"nodemon": "^2.0.15",
|
|
55
|
-
"puppeteer": "^1.20.0",
|
|
56
|
-
"sass-loader": "^12.4.0",
|
|
57
|
-
"source-map-loader": "^3.0.0",
|
|
58
|
-
"style-loader": "^3.3.1",
|
|
59
|
-
"tape": "^4.9.1",
|
|
60
|
-
"terser-webpack-plugin": "^5.3.0",
|
|
61
|
-
"uglify-es": "^3.3.9",
|
|
62
|
-
"vue-loader": "^17.0.0",
|
|
63
|
-
"vue-template-compiler": "^2.6.14",
|
|
64
|
-
"webpack": "^5.65.0",
|
|
65
|
-
"webpack-cli": "^4.9.1",
|
|
66
|
-
"worker-loader": "^3.0.8"
|
|
55
|
+
"duckdb": "^1.4.4"
|
|
67
56
|
}
|
|
68
57
|
}
|