tranfi 0.0.2 → 0.2.0

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.
Files changed (151) hide show
  1. package/LICENSE +177 -21
  2. package/NOTICE +8 -0
  3. package/README.md +627 -0
  4. package/app/assets/index-6quYZ5Ap.css +5 -0
  5. package/app/assets/index-BIAIKnrp.js +160 -0
  6. package/app/assets/materialdesignicons-webfont-B7mPwVP_.ttf +0 -0
  7. package/app/assets/materialdesignicons-webfont-CSr8KVlo.eot +0 -0
  8. package/app/assets/materialdesignicons-webfont-Dp5v-WZN.woff2 +0 -0
  9. package/app/assets/materialdesignicons-webfont-PXm3-2wK.woff +0 -0
  10. package/app/index.html +13 -0
  11. package/binding.gyp +121 -0
  12. package/csrc/arena.c +93 -0
  13. package/csrc/batch.c +976 -0
  14. package/csrc/buffer.c +154 -0
  15. package/csrc/cJSON.c +3386 -0
  16. package/csrc/cJSON.h +316 -0
  17. package/csrc/codec_csv.c +1951 -0
  18. package/csrc/codec_jsonl.c +1086 -0
  19. package/csrc/codec_table.c +248 -0
  20. package/csrc/codec_text.c +447 -0
  21. package/csrc/compiler.c +130 -0
  22. package/csrc/config.h +21 -0
  23. package/csrc/date_utils.h +94 -0
  24. package/csrc/dsl.c +5417 -0
  25. package/csrc/dsl.h +22 -0
  26. package/csrc/expr.c +1553 -0
  27. package/csrc/expr.h +58 -0
  28. package/csrc/internal.h +539 -0
  29. package/csrc/ir.c +166 -0
  30. package/csrc/ir.h +208 -0
  31. package/csrc/ir_schema.c +75 -0
  32. package/csrc/ir_serialize.c +166 -0
  33. package/csrc/ir_sql.c +1822 -0
  34. package/csrc/ir_validate.c +576 -0
  35. package/csrc/json_path.c +210 -0
  36. package/csrc/main.c +1241 -0
  37. package/csrc/memory_estimate.c +477 -0
  38. package/csrc/op_acf.c +283 -0
  39. package/csrc/op_across.c +477 -0
  40. package/csrc/op_anomaly.c +255 -0
  41. package/csrc/op_assert.c +761 -0
  42. package/csrc/op_bin.c +248 -0
  43. package/csrc/op_cast.c +523 -0
  44. package/csrc/op_clip.c +99 -0
  45. package/csrc/op_date_trunc.c +355 -0
  46. package/csrc/op_datetime.c +394 -0
  47. package/csrc/op_derive.c +216 -0
  48. package/csrc/op_diff.c +250 -0
  49. package/csrc/op_ewma.c +222 -0
  50. package/csrc/op_explode.c +206 -0
  51. package/csrc/op_fill_down.c +235 -0
  52. package/csrc/op_fill_null.c +268 -0
  53. package/csrc/op_filter.c +181 -0
  54. package/csrc/op_frequency.c +721 -0
  55. package/csrc/op_grep.c +181 -0
  56. package/csrc/op_group_agg.c +1956 -0
  57. package/csrc/op_hash.c +159 -0
  58. package/csrc/op_head.c +84 -0
  59. package/csrc/op_interpolate.c +445 -0
  60. package/csrc/op_join.c +2902 -0
  61. package/csrc/op_json_extract.c +227 -0
  62. package/csrc/op_json_filter.c +384 -0
  63. package/csrc/op_json_flatten.c +293 -0
  64. package/csrc/op_json_schema.c +503 -0
  65. package/csrc/op_label_encode.c +419 -0
  66. package/csrc/op_lag.c +181 -0
  67. package/csrc/op_lead.c +242 -0
  68. package/csrc/op_normalize.c +510 -0
  69. package/csrc/op_onehot.c +457 -0
  70. package/csrc/op_pivot.c +1754 -0
  71. package/csrc/op_quarantine.c +189 -0
  72. package/csrc/op_registry.c +3044 -0
  73. package/csrc/op_rename.c +129 -0
  74. package/csrc/op_replace.c +354 -0
  75. package/csrc/op_rleid.c +297 -0
  76. package/csrc/op_rowid.c +559 -0
  77. package/csrc/op_sample.c +158 -0
  78. package/csrc/op_schema.c +1341 -0
  79. package/csrc/op_schema_infer.c +252 -0
  80. package/csrc/op_select.c +340 -0
  81. package/csrc/op_set.c +3449 -0
  82. package/csrc/op_skip.c +95 -0
  83. package/csrc/op_sort.c +819 -0
  84. package/csrc/op_source_name.c +120 -0
  85. package/csrc/op_split.c +151 -0
  86. package/csrc/op_split_data.c +119 -0
  87. package/csrc/op_stack.c +271 -0
  88. package/csrc/op_stats.c +875 -0
  89. package/csrc/op_step.c +333 -0
  90. package/csrc/op_tail.c +105 -0
  91. package/csrc/op_tee.c +338 -0
  92. package/csrc/op_top.c +357 -0
  93. package/csrc/op_trim.c +138 -0
  94. package/csrc/op_unique.c +1343 -0
  95. package/csrc/op_unpivot.c +193 -0
  96. package/csrc/op_validate.c +648 -0
  97. package/csrc/op_window.c +591 -0
  98. package/csrc/path_policy.c +85 -0
  99. package/csrc/pipeline.c +1088 -0
  100. package/csrc/recipes.c +104 -0
  101. package/csrc/recipes.h +27 -0
  102. package/csrc/report.c +506 -0
  103. package/csrc/report.h +22 -0
  104. package/csrc/selector.c +1097 -0
  105. package/csrc/size_utils.c +348 -0
  106. package/csrc/spill.c +317 -0
  107. package/csrc/spill.h +21 -0
  108. package/csrc/tranfi.h +291 -0
  109. package/csrc/transform.h +209 -0
  110. package/csrc/transform_api.c +2237 -0
  111. package/csrc/transform_categorical.c +923 -0
  112. package/csrc/transform_internal.h +472 -0
  113. package/csrc/transform_json.c +3812 -0
  114. package/csrc/transform_numeric.c +1966 -0
  115. package/csrc/transform_sha256.c +154 -0
  116. package/csrc/transform_wasm.h +162 -0
  117. package/csrc/transform_wasm_api.c +1373 -0
  118. package/csrc/wasm_api.c +218 -0
  119. package/napi_api.c +534 -0
  120. package/napi_transform.c +1648 -0
  121. package/napi_transform.h +8 -0
  122. package/package.json +64 -59
  123. package/scripts/install-native.js +76 -0
  124. package/scripts/prepack.js +64 -0
  125. package/scripts/sync-csrc.js +23 -0
  126. package/src/cli.js +190 -0
  127. package/src/engines/duckdb.js +142 -0
  128. package/src/index.js +925 -0
  129. package/src/memory_policy.js +411 -0
  130. package/src/native.js +18 -0
  131. package/src/pipeline.js +709 -0
  132. package/src/recipe_json.js +80 -0
  133. package/src/server.js +279 -0
  134. package/src/transform.js +403 -0
  135. package/src/transform_error.js +10 -0
  136. package/src/wasm.js +21 -0
  137. package/wasm/index.js +732 -0
  138. package/wasm/package.json +1 -0
  139. package/wasm/tranfi_core.js +0 -0
  140. package/wasm/transform.js +1156 -0
  141. package/wasm/worker.js +786 -0
  142. package/dist/bundle.js +0 -1
  143. package/index.html +0 -18
  144. package/src/app.css +0 -169
  145. package/src/app.js +0 -203
  146. package/src/app.vue +0 -250
  147. package/src/bulma-input.vue +0 -110
  148. package/src/common-inputs.js +0 -28
  149. package/src/main.js +0 -20
  150. package/src/transforms.js +0 -166
  151. package/webpack.config.js +0 -108
package/csrc/op_bin.c ADDED
@@ -0,0 +1,248 @@
1
+ /*
2
+ * op_bin.c — Discretize numeric column into labeled bins.
3
+ *
4
+ * Config: {"column": "age", "boundaries": [18, 30, 50, 65]}
5
+ * Adds <col>_bin column with labels like "<18", "18-30", "30-50", "50-65", "65+"
6
+ */
7
+
8
+ #include "internal.h"
9
+ #include "cJSON.h"
10
+ #include <stdlib.h>
11
+ #include <string.h>
12
+ #include <stdio.h>
13
+ #include <math.h>
14
+
15
+ typedef enum {
16
+ BIN_MISSING_ERROR,
17
+ BIN_MISSING_NULL,
18
+ BIN_MISSING_IGNORE,
19
+ } bin_missing_policy;
20
+
21
+ typedef enum {
22
+ BIN_TYPE_FAIL,
23
+ BIN_TYPE_NULL,
24
+ } bin_type_policy;
25
+
26
+ typedef struct {
27
+ char *column;
28
+ double *boundaries;
29
+ size_t n_boundaries;
30
+ bin_missing_policy missing;
31
+ bin_type_policy on_type_error;
32
+ } bin_state;
33
+
34
+ static int bin_is_numeric_type(tf_type type) {
35
+ return type == TF_TYPE_INT64 || type == TF_TYPE_FLOAT64;
36
+ }
37
+
38
+ static double bin_get_numeric(const tf_batch *b, size_t r, int ci) {
39
+ if (b->col_types[ci] == TF_TYPE_INT64) return (double)tf_batch_get_int64(b, r, ci);
40
+ return tf_batch_get_float64(b, r, ci);
41
+ }
42
+
43
+ static void bin_set_col_error(const char *column, const char *suffix) {
44
+ char msg[512];
45
+ snprintf(msg, sizeof(msg), "bin: column '%s' %s", column ? column : "", suffix);
46
+ tf_set_last_error(msg);
47
+ }
48
+
49
+ static int bin_parse_missing_policy(const cJSON *args, bin_missing_policy *out) {
50
+ *out = BIN_MISSING_ERROR;
51
+ const cJSON *j = cJSON_GetObjectItemCaseSensitive(args, "missing");
52
+ if (!j) return TF_OK;
53
+ if (!cJSON_IsString(j)) {
54
+ tf_set_last_error("bin: missing must be error, null, or ignore");
55
+ return TF_ERROR;
56
+ }
57
+ if (strcmp(j->valuestring, "error") == 0) *out = BIN_MISSING_ERROR;
58
+ else if (strcmp(j->valuestring, "null") == 0) *out = BIN_MISSING_NULL;
59
+ else if (strcmp(j->valuestring, "ignore") == 0) *out = BIN_MISSING_IGNORE;
60
+ else {
61
+ tf_set_last_error("bin: missing must be error, null, or ignore");
62
+ return TF_ERROR;
63
+ }
64
+ return TF_OK;
65
+ }
66
+
67
+ static int bin_parse_type_policy(const cJSON *args, bin_type_policy *out) {
68
+ *out = BIN_TYPE_FAIL;
69
+ const cJSON *j = cJSON_GetObjectItemCaseSensitive(args, "on_type_error");
70
+ if (!j) return TF_OK;
71
+ if (!cJSON_IsString(j)) {
72
+ tf_set_last_error("bin: on_type_error must be fail or null");
73
+ return TF_ERROR;
74
+ }
75
+ if (strcmp(j->valuestring, "fail") == 0) *out = BIN_TYPE_FAIL;
76
+ else if (strcmp(j->valuestring, "null") == 0) *out = BIN_TYPE_NULL;
77
+ else {
78
+ tf_set_last_error("bin: on_type_error must be fail or null");
79
+ return TF_ERROR;
80
+ }
81
+ return TF_OK;
82
+ }
83
+
84
+ static int bin_passthrough(tf_batch *in, tf_batch **out) {
85
+ tf_batch *ob = tf_batch_create(in->n_cols, in->n_rows);
86
+ if (!ob) return TF_ERROR;
87
+ if (tf_batch_clone_schema(ob, in) != TF_OK) {
88
+ tf_batch_free(ob);
89
+ return TF_ERROR;
90
+ }
91
+ for (size_t r = 0; r < in->n_rows; r++) {
92
+ if (tf_batch_copy_row(ob, r, in, r) != TF_OK) {
93
+ tf_batch_free(ob);
94
+ return TF_ERROR;
95
+ }
96
+ if (tf_batch_expose_row(ob, r) != TF_OK) {
97
+ tf_batch_free(ob);
98
+ return TF_ERROR;
99
+ }
100
+ }
101
+ *out = ob;
102
+ return TF_OK;
103
+ }
104
+
105
+ static int bin_process(tf_step *self, tf_batch *in, tf_batch **out,
106
+ tf_side_channels *side) {
107
+ (void)side;
108
+ bin_state *st = self->state;
109
+ *out = NULL;
110
+
111
+ int ci = tf_batch_col_index(in, st->column);
112
+ int force_null = 0;
113
+ if (ci < 0) {
114
+ if (st->missing == BIN_MISSING_ERROR) {
115
+ bin_set_col_error(st->column, "not found");
116
+ return TF_ERROR;
117
+ }
118
+ if (st->missing == BIN_MISSING_IGNORE) return bin_passthrough(in, out);
119
+ force_null = 1;
120
+ } else if (!bin_is_numeric_type(in->col_types[ci])) {
121
+ if (st->on_type_error == BIN_TYPE_FAIL) {
122
+ bin_set_col_error(st->column, "must be numeric");
123
+ return TF_ERROR;
124
+ }
125
+ force_null = 1;
126
+ }
127
+
128
+ char *bin_col_name = tf_string_append_suffix_checked(st->column, "_bin");
129
+ if (!bin_col_name) return TF_ERROR;
130
+ const char *extra_names[1] = {bin_col_name};
131
+ tf_type extra_types[1] = {TF_TYPE_STRING};
132
+ tf_batch *ob = tf_batch_create(in->n_cols + 1, in->n_rows);
133
+ if (!ob) {
134
+ free(bin_col_name);
135
+ return TF_ERROR;
136
+ }
137
+ if (tf_batch_clone_with_extra_cols(ob, in, extra_names, extra_types, 1) != TF_OK) {
138
+ free(bin_col_name);
139
+ tf_batch_free(ob);
140
+ return TF_ERROR;
141
+ }
142
+ free(bin_col_name);
143
+
144
+ for (size_t r = 0; r < in->n_rows; r++) {
145
+ if (tf_batch_copy_row(ob, r, in, r) != TF_OK) {
146
+ tf_batch_free(ob);
147
+ return TF_ERROR;
148
+ }
149
+
150
+ if (force_null || tf_batch_is_null(in, r, ci)) {
151
+ if (tf_batch_set_null(ob, r, in->n_cols) != TF_OK) { tf_batch_free(ob); return TF_ERROR; }
152
+ } else {
153
+ double val = bin_get_numeric(in, r, ci);
154
+
155
+ char label[64];
156
+ if (st->n_boundaries == 0) {
157
+ snprintf(label, sizeof(label), TF_FLOAT64_ROUNDTRIP_FORMAT, val);
158
+ } else if (val < st->boundaries[0]) {
159
+ snprintf(label, sizeof(label), "<" TF_FLOAT64_ROUNDTRIP_FORMAT, st->boundaries[0]);
160
+ } else {
161
+ size_t b;
162
+ for (b = 1; b < st->n_boundaries; b++) {
163
+ if (val < st->boundaries[b]) break;
164
+ }
165
+ if (b < st->n_boundaries) {
166
+ snprintf(label, sizeof(label), TF_FLOAT64_ROUNDTRIP_FORMAT "-" TF_FLOAT64_ROUNDTRIP_FORMAT, st->boundaries[b - 1], st->boundaries[b]);
167
+ } else {
168
+ snprintf(label, sizeof(label), TF_FLOAT64_ROUNDTRIP_FORMAT "+", st->boundaries[st->n_boundaries - 1]);
169
+ }
170
+ }
171
+ if (tf_batch_set_string(ob, r, in->n_cols, label) != TF_OK) {
172
+ tf_batch_free(ob);
173
+ return TF_ERROR;
174
+ }
175
+ }
176
+ if (tf_batch_expose_row(ob, r) != TF_OK) {
177
+ tf_batch_free(ob);
178
+ return TF_ERROR;
179
+ }
180
+ }
181
+
182
+ *out = ob;
183
+ return TF_OK;
184
+ }
185
+
186
+ static int bin_flush(tf_step *self, tf_batch **out, tf_side_channels *side) {
187
+ (void)self; (void)side; *out = NULL; return TF_OK;
188
+ }
189
+
190
+ static void bin_destroy(tf_step *self) {
191
+ bin_state *st = self->state;
192
+ if (st) { free(st->column); free(st->boundaries); free(st); }
193
+ free(self);
194
+ }
195
+
196
+ tf_step *tf_bin_create(const cJSON *args) {
197
+ if (!args) return NULL;
198
+ cJSON *col_j = cJSON_GetObjectItemCaseSensitive(args, "column");
199
+ if (!cJSON_IsString(col_j) || !col_j->valuestring[0]) {
200
+ tf_set_last_error("bin: column is required");
201
+ return NULL;
202
+ }
203
+
204
+ bin_state *st = tf_callocarray_checked(1, sizeof(bin_state));
205
+ if (!st) return NULL;
206
+ st->column = tf_strdup_checked(col_j->valuestring);
207
+ if (!st->column) { free(st); return NULL; }
208
+ if (bin_parse_missing_policy(args, &st->missing) != TF_OK ||
209
+ bin_parse_type_policy(args, &st->on_type_error) != TF_OK) {
210
+ free(st->column);
211
+ free(st);
212
+ return NULL;
213
+ }
214
+
215
+ cJSON *bounds = cJSON_GetObjectItemCaseSensitive(args, "boundaries");
216
+ if (!bounds || !cJSON_IsArray(bounds)) {
217
+ tf_set_last_error("bin: boundaries must be an array");
218
+ free(st->column);
219
+ free(st);
220
+ return NULL;
221
+ }
222
+ int n = cJSON_GetArraySize(bounds);
223
+ if (n > 0) {
224
+ st->boundaries = tf_mallocarray_checked((size_t)n, sizeof(double));
225
+ if (!st->boundaries) { free(st->column); free(st); return NULL; }
226
+ st->n_boundaries = (size_t)n;
227
+ for (int i = 0; i < n; i++) {
228
+ cJSON *item = cJSON_GetArrayItem(bounds, i);
229
+ if (!cJSON_IsNumber(item) || !isfinite(item->valuedouble)) {
230
+ tf_set_last_error("bin: boundaries must be finite, strictly increasing numbers");
231
+ free(st->column); free(st->boundaries); free(st); return NULL;
232
+ }
233
+ if (i > 0 && item->valuedouble <= st->boundaries[i - 1]) {
234
+ tf_set_last_error("bin: boundaries must be finite, strictly increasing numbers");
235
+ free(st->column); free(st->boundaries); free(st); return NULL;
236
+ }
237
+ st->boundaries[i] = item->valuedouble;
238
+ }
239
+ }
240
+
241
+ tf_step *step = tf_callocarray_checked(1, sizeof(tf_step));
242
+ if (!step) { free(st->column); free(st->boundaries); free(st); return NULL; }
243
+ step->process = bin_process;
244
+ step->flush = bin_flush;
245
+ step->destroy = bin_destroy;
246
+ step->state = st;
247
+ return step;
248
+ }