alef 0.83.2

Opinionated polyglot binding generator for Rust libraries
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
use super::*;

/// The exact shape `scaffold_wasm` emitted before the fix that added the `exports` map --
/// a single `nodejs` target, `main`/`module`/`types` all pointing at the same crate file.
fn pre_fix_package_json() -> String {
    "{\n  \
     \"name\": \"@scope/example-wasm\",\n  \
     \"version\": \"1.0.0\",\n  \
     \"private\": false,\n  \
     \"description\": \"An example crate\",\n  \
     \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \
     \"type\": \"module\",\n  \
     \"files\": [\n    \"pkg/nodejs\",\n    \"README.md\"\n  ],\n  \
     \"main\": \"pkg/nodejs/example_wasm.js\",\n  \
     \"module\": \"pkg/nodejs/example_wasm.js\",\n  \
     \"types\": \"pkg/nodejs/example_wasm.d.ts\",\n  \
     \"engines\": {\n    \"node\": \">=18\"\n  },\n  \
     \"scripts\": {\n    \"build\": \"wasm-pack build\"\n  }\n\
     }\n"
    .to_string()
}

#[test]
fn should_insert_exports_map_when_missing_from_alef_authored_package_json() {
    let dir = tempfile::tempdir().expect("tempdir");
    let pkg_dir = dir.path().join("crates/example-wasm");
    std::fs::create_dir_all(&pkg_dir).expect("create crates/example-wasm");
    std::fs::write(pkg_dir.join("package.json"), pre_fix_package_json()).expect("write pre-fix package.json");

    let relative_path = Path::new("crates/example-wasm/package.json");
    let changed = migrate_wasm_package_json_exports(dir.path(), relative_path).expect("migration must not error");
    assert!(changed, "a package.json missing exports must be reported as changed");

    let on_disk = std::fs::read_to_string(pkg_dir.join("package.json")).expect("read migrated file");
    let parsed: serde_json::Value = serde_json::from_str(&on_disk).expect("migrated file must be valid JSON");
    assert_eq!(
        parsed["exports"]["."]["types"], "./pkg/nodejs/example_wasm.d.ts",
        "exports map must reference the same target/crate_file as the existing main/module/types fields"
    );
    assert_eq!(parsed["exports"]["."]["require"], "./pkg/nodejs/example_wasm.js");
    assert_eq!(
        parsed["name"], "@scope/example-wasm",
        "fields outside exports must survive untouched"
    );
    assert_eq!(
        parsed["scripts"]["build"], "wasm-pack build",
        "user-visible fields must survive untouched"
    );

    let changed_again =
        migrate_wasm_package_json_exports(dir.path(), relative_path).expect("second pass must not error");
    assert!(
        !changed_again,
        "second pass over an already-migrated file must be a no-op"
    );
}

#[test]
fn should_not_touch_a_package_json_that_already_has_exports() {
    let dir = tempfile::tempdir().expect("tempdir");
    let pkg_dir = dir.path().join("crates/example-wasm");
    std::fs::create_dir_all(&pkg_dir).expect("create crates/example-wasm");
    let hand_written = "{\n  \"name\": \"@scope/example-wasm\",\n  \"exports\": \"./custom.js\"\n}\n";
    std::fs::write(pkg_dir.join("package.json"), hand_written).expect("write hand-edited package.json");

    let relative_path = Path::new("crates/example-wasm/package.json");
    let changed = migrate_wasm_package_json_exports(dir.path(), relative_path).expect("migration must not error");
    assert!(
        !changed,
        "a package.json that already declares exports must never be touched"
    );

    let on_disk = std::fs::read_to_string(pkg_dir.join("package.json")).expect("read file");
    assert_eq!(
        on_disk, hand_written,
        "a custom exports field must survive byte-for-byte"
    );
}

#[test]
fn should_not_touch_a_foreign_package_json_without_the_alef_wasm_shape() {
    let dir = tempfile::tempdir().expect("tempdir");
    let pkg_dir = dir.path().join("crates/example-wasm");
    std::fs::create_dir_all(&pkg_dir).expect("create crates/example-wasm");
    let hand_written = concat!(
        "{\n",
        "  \"name\": \"example\",\n",
        "  \"main\": \"index.js\",\n",
        "  \"engines\": {\n",
        "    \"node\": \">=18\"\n",
        "  }\n",
        "}\n",
    );
    std::fs::write(pkg_dir.join("package.json"), hand_written).expect("write foreign package.json");

    let relative_path = Path::new("crates/example-wasm/package.json");
    let changed = migrate_wasm_package_json_exports(dir.path(), relative_path).expect("migration must not error");
    assert!(
        !changed,
        "a package.json without alef's main/module/types shape must never be touched"
    );

    let on_disk = std::fs::read_to_string(pkg_dir.join("package.json")).expect("read file");
    assert_eq!(
        on_disk, hand_written,
        "a foreign package.json must survive byte-for-byte"
    );
}

#[test]
fn migrate_wasm_package_json_is_a_no_op_when_file_does_not_exist() {
    let dir = tempfile::tempdir().expect("tempdir");
    let relative_path = Path::new("crates/example-wasm/package.json");
    let changed = migrate_wasm_package_json_exports(dir.path(), relative_path).expect("must not error");
    assert!(!changed);
    assert!(!dir.path().join(relative_path).exists());
}

/// The shape `scaffold_wasm` emitted before the fix that declared `vitest` (and its coverage
/// provider) as devDependencies: the alef main/module/types fingerprint and every test script
/// are present, but `devDependencies` does not exist at all -- the true pre-fix state of every
/// consumer crate scaffolded before that fix shipped. `scripts` is deliberately the last
/// top-level key, matching the exact `  }\n}` tail [`insert_new_dev_dependencies_block`]
/// anchors on.
fn pre_vitest_fix_package_json() -> String {
    concat!(
        "{\n",
        "  \"name\": \"@scope/example-wasm\",\n",
        "  \"version\": \"1.0.0\",\n",
        "  \"private\": false,\n",
        "  \"main\": \"pkg/nodejs/example_wasm.js\",\n",
        "  \"module\": \"pkg/nodejs/example_wasm.js\",\n",
        "  \"types\": \"pkg/nodejs/example_wasm.d.ts\",\n",
        "  \"engines\": {\n",
        "    \"node\": \">= 22\"\n",
        "  },\n",
        "  \"scripts\": {\n",
        "    \"build\": \"wasm-pack build --target nodejs --out-dir pkg/nodejs\",\n",
        "    \"test\": \"vitest run\",\n",
        "    \"test:watch\": \"vitest watch\",\n",
        "    \"test:coverage\": \"vitest run --coverage\",\n",
        "    \"clean\": \"rm -rf pkg dist\"\n",
        "  }\n",
        "}\n",
    )
    .to_string()
}

/// EXISTING Alef-authored population, no `devDependencies` key at all: migration must insert
/// a whole new block declaring both `vitest` and its coverage provider, and must not disturb
/// any other field. Also proves idempotency at the file level: a second run makes no further
/// change, and the bytes on disk after the second run are identical to the bytes after the
/// first.
#[test]
fn should_insert_full_dev_dependencies_block_for_pre_vitest_fix_package_json() {
    let dir = tempfile::tempdir().expect("tempdir");
    let pkg_dir = dir.path().join("crates/example-wasm");
    std::fs::create_dir_all(&pkg_dir).expect("create crates/example-wasm");
    std::fs::write(pkg_dir.join("package.json"), pre_vitest_fix_package_json()).expect("write pre-fix package.json");
    let relative_path = Path::new("crates/example-wasm/package.json");

    let changed =
        migrate_wasm_package_json_vitest_dev_dependencies(dir.path(), relative_path).expect("migration must not error");
    assert!(
        changed,
        "a package.json missing devDependencies must be reported as changed"
    );

    let after_first = std::fs::read_to_string(pkg_dir.join("package.json")).expect("read migrated file");
    let parsed: serde_json::Value = serde_json::from_str(&after_first).expect("migrated file must be valid JSON");
    assert_eq!(
        parsed["devDependencies"]["vitest"],
        tv::npm::VITEST,
        "must pin vitest to the central registry version, got:\n{parsed:#}"
    );
    assert_eq!(
        parsed["devDependencies"]["@vitest/coverage-v8"],
        tv::npm::VITEST_COVERAGE_V8,
        "must pin the coverage provider to the central registry version, got:\n{parsed:#}"
    );
    assert_eq!(
        parsed["name"], "@scope/example-wasm",
        "fields outside devDependencies must survive untouched"
    );
    assert_eq!(
        parsed["scripts"]["clean"], "rm -rf pkg dist",
        "scripts must survive untouched"
    );

    let changed_again = migrate_wasm_package_json_vitest_dev_dependencies(dir.path(), relative_path)
        .expect("second pass must not error");
    assert!(
        !changed_again,
        "second pass over an already-migrated file must be a no-op"
    );
    let after_second = std::fs::read_to_string(pkg_dir.join("package.json")).expect("read file after second pass");
    assert_eq!(
        after_first, after_second,
        "a second migration pass must produce byte-identical output to the first"
    );
}

/// EXISTING Alef-authored population, `devDependencies` already present with `vitest` pinned
/// to a value a consumer chose themselves (not the central registry's current value):
/// migration must add only the missing coverage provider and must never overwrite the
/// consumer's own `vitest` pin.
#[test]
fn should_add_only_the_missing_coverage_provider_and_never_overwrite_an_existing_vitest_pin() {
    let dir = tempfile::tempdir().expect("tempdir");
    let pkg_dir = dir.path().join("crates/example-wasm");
    std::fs::create_dir_all(&pkg_dir).expect("create crates/example-wasm");
    let fixture = concat!(
        "{\n",
        "  \"name\": \"@scope/example-wasm\",\n",
        "  \"main\": \"pkg/nodejs/example_wasm.js\",\n",
        "  \"module\": \"pkg/nodejs/example_wasm.js\",\n",
        "  \"types\": \"pkg/nodejs/example_wasm.d.ts\",\n",
        "  \"engines\": {\n",
        "    \"node\": \">= 22\"\n",
        "  },\n",
        "  \"scripts\": {\n",
        "    \"test\": \"vitest run\",\n",
        "    \"test:watch\": \"vitest watch\",\n",
        "    \"test:coverage\": \"vitest run --coverage\"\n",
        "  },\n",
        "  \"devDependencies\": {\n",
        "    \"vitest\": \"1.2.3\"\n",
        "  }\n",
        "}\n",
    );
    std::fs::write(pkg_dir.join("package.json"), fixture).expect("write fixture package.json");
    let relative_path = Path::new("crates/example-wasm/package.json");

    let changed =
        migrate_wasm_package_json_vitest_dev_dependencies(dir.path(), relative_path).expect("migration must not error");
    assert!(
        changed,
        "a package.json missing only the coverage provider must be reported as changed"
    );

    let after_first = std::fs::read_to_string(pkg_dir.join("package.json")).expect("read migrated file");
    let parsed: serde_json::Value = serde_json::from_str(&after_first).expect("migrated file must be valid JSON");
    assert_eq!(
        parsed["devDependencies"]["vitest"], "1.2.3",
        "an existing consumer-chosen vitest pin must never be overwritten, got:\n{parsed:#}"
    );
    assert_eq!(
        parsed["devDependencies"]["@vitest/coverage-v8"],
        tv::npm::VITEST_COVERAGE_V8,
        "must add the coverage provider pinned to the central registry version, got:\n{parsed:#}"
    );

    let changed_again = migrate_wasm_package_json_vitest_dev_dependencies(dir.path(), relative_path)
        .expect("second pass must not error");
    assert!(
        !changed_again,
        "second pass over an already-migrated file must be a no-op"
    );
    let after_second = std::fs::read_to_string(pkg_dir.join("package.json")).expect("read file after second pass");
    assert_eq!(
        after_first, after_second,
        "a second migration pass must produce byte-identical output to the first"
    );
}

/// EXISTING Alef-authored population with a consumer's own unrelated dev dependency already
/// present: migration must add the missing `vitest`/coverage entries without disturbing the
/// consumer's own entry in any way.
#[test]
fn should_preserve_a_consumer_added_dev_dependency_while_inserting_the_missing_ones() {
    let dir = tempfile::tempdir().expect("tempdir");
    let pkg_dir = dir.path().join("crates/example-wasm");
    std::fs::create_dir_all(&pkg_dir).expect("create crates/example-wasm");
    let fixture = concat!(
        "{\n",
        "  \"name\": \"@scope/example-wasm\",\n",
        "  \"main\": \"pkg/nodejs/example_wasm.js\",\n",
        "  \"module\": \"pkg/nodejs/example_wasm.js\",\n",
        "  \"types\": \"pkg/nodejs/example_wasm.d.ts\",\n",
        "  \"engines\": {\n",
        "    \"node\": \">= 22\"\n",
        "  },\n",
        "  \"scripts\": {\n",
        "    \"test\": \"vitest run\",\n",
        "    \"test:watch\": \"vitest watch\",\n",
        "    \"test:coverage\": \"vitest run --coverage\"\n",
        "  },\n",
        "  \"devDependencies\": {\n",
        "    \"typescript\": \"^7.0.0\"\n",
        "  }\n",
        "}\n",
    );
    std::fs::write(pkg_dir.join("package.json"), fixture).expect("write fixture package.json");
    let relative_path = Path::new("crates/example-wasm/package.json");

    let changed =
        migrate_wasm_package_json_vitest_dev_dependencies(dir.path(), relative_path).expect("migration must not error");
    assert!(changed);

    let on_disk = std::fs::read_to_string(pkg_dir.join("package.json")).expect("read migrated file");
    let parsed: serde_json::Value = serde_json::from_str(&on_disk).expect("migrated file must be valid JSON");
    assert_eq!(
        parsed["devDependencies"]["typescript"], "^7.0.0",
        "a consumer-added, unrelated dev dependency must survive untouched, got:\n{parsed:#}"
    );
    assert_eq!(parsed["devDependencies"]["vitest"], tv::npm::VITEST);
    assert_eq!(
        parsed["devDependencies"]["@vitest/coverage-v8"],
        tv::npm::VITEST_COVERAGE_V8
    );
}

/// FOREIGN/unrecognized population, case 1: no alef main/module/types fingerprint at all,
/// even though the file happens to run vitest -- must never be touched. This is the safety
/// case: a false positive here would silently rewrite a user's hand-maintained package.json.
#[test]
fn should_not_touch_a_foreign_vitest_package_json_without_the_alef_wasm_shape() {
    let dir = tempfile::tempdir().expect("tempdir");
    let pkg_dir = dir.path().join("crates/example-wasm");
    std::fs::create_dir_all(&pkg_dir).expect("create crates/example-wasm");
    let hand_written = concat!(
        "{\n",
        "  \"name\": \"example\",\n",
        "  \"main\": \"index.js\",\n",
        "  \"scripts\": {\n",
        "    \"test\": \"vitest run\"\n",
        "  }\n",
        "}\n",
    );
    std::fs::write(pkg_dir.join("package.json"), hand_written).expect("write foreign package.json");
    let relative_path = Path::new("crates/example-wasm/package.json");

    let changed =
        migrate_wasm_package_json_vitest_dev_dependencies(dir.path(), relative_path).expect("migration must not error");
    assert!(
        !changed,
        "a package.json without alef's main/module/types shape must never be touched"
    );
    let on_disk = std::fs::read_to_string(pkg_dir.join("package.json")).expect("read file");
    assert_eq!(
        on_disk, hand_written,
        "a foreign package.json must survive byte-for-byte"
    );
}

/// FOREIGN/unrecognized population, case 2: the alef main/module/types fingerprint is
/// present, but the exact `"test": "vitest run"` script this migration anchors on is not --
/// proving the second, independent anchor also guards against a false positive on a file that
/// merely looks alef-shaped at the build-output level. Must never be touched.
#[test]
fn should_not_touch_an_alef_shaped_package_json_missing_the_vitest_test_script() {
    let dir = tempfile::tempdir().expect("tempdir");
    let pkg_dir = dir.path().join("crates/example-wasm");
    std::fs::create_dir_all(&pkg_dir).expect("create crates/example-wasm");
    let hand_written = concat!(
        "{\n",
        "  \"name\": \"@scope/example-wasm\",\n",
        "  \"main\": \"pkg/nodejs/example_wasm.js\",\n",
        "  \"module\": \"pkg/nodejs/example_wasm.js\",\n",
        "  \"types\": \"pkg/nodejs/example_wasm.d.ts\",\n",
        "  \"scripts\": {\n",
        "    \"build\": \"wasm-pack build\"\n",
        "  }\n",
        "}\n",
    );
    std::fs::write(pkg_dir.join("package.json"), hand_written).expect("write foreign package.json");
    let relative_path = Path::new("crates/example-wasm/package.json");

    let changed =
        migrate_wasm_package_json_vitest_dev_dependencies(dir.path(), relative_path).expect("migration must not error");
    assert!(
        !changed,
        "a package.json without the exact vitest test script anchor must never be touched"
    );
    let on_disk = std::fs::read_to_string(pkg_dir.join("package.json")).expect("read file");
    assert_eq!(
        on_disk, hand_written,
        "a foreign package.json must survive byte-for-byte"
    );
}

/// FOREIGN/unrecognized population, case 3: both `vitest` and the coverage provider are
/// already declared (whatever their values), so there is nothing to add. Also the terminal
/// idempotency state every other test's second pass converges on.
#[test]
fn should_not_touch_a_package_json_that_already_declares_both_dependencies() {
    let dir = tempfile::tempdir().expect("tempdir");
    let pkg_dir = dir.path().join("crates/example-wasm");
    std::fs::create_dir_all(&pkg_dir).expect("create crates/example-wasm");
    let hand_written = concat!(
        "{\n",
        "  \"name\": \"@scope/example-wasm\",\n",
        "  \"main\": \"pkg/nodejs/example_wasm.js\",\n",
        "  \"module\": \"pkg/nodejs/example_wasm.js\",\n",
        "  \"types\": \"pkg/nodejs/example_wasm.d.ts\",\n",
        "  \"scripts\": {\n",
        "    \"test\": \"vitest run\",\n",
        "    \"test:coverage\": \"vitest run --coverage\"\n",
        "  },\n",
        "  \"devDependencies\": {\n",
        "    \"vitest\": \"9.9.9\",\n",
        "    \"@vitest/coverage-v8\": \"9.9.9\"\n",
        "  }\n",
        "}\n",
    );
    std::fs::write(pkg_dir.join("package.json"), hand_written).expect("write already-complete package.json");
    let relative_path = Path::new("crates/example-wasm/package.json");

    let changed =
        migrate_wasm_package_json_vitest_dev_dependencies(dir.path(), relative_path).expect("migration must not error");
    assert!(
        !changed,
        "a package.json declaring both dependencies must never be touched"
    );
    let on_disk = std::fs::read_to_string(pkg_dir.join("package.json")).expect("read file");
    assert_eq!(
        on_disk, hand_written,
        "an already-complete package.json must survive byte-for-byte"
    );
}

/// Idempotency of the pure transform itself, independent of the file-system round trip above:
/// applying it once to the pre-fix fixture produces a migration; applying it again to that
/// migrated string finds nothing left to add.
#[test]
fn repair_wasm_vitest_dev_dependencies_is_idempotent_at_the_string_level() {
    let fixture = pre_vitest_fix_package_json();
    let once = repair_missing_wasm_vitest_dev_dependencies(&fixture).expect("first pass must migrate");
    let twice = repair_missing_wasm_vitest_dev_dependencies(&once);
    assert!(
        twice.is_none(),
        "a second pass over already-migrated content must find nothing left to add, got:\n{twice:?}"
    );
}

#[test]
fn migrate_wasm_package_json_vitest_dev_dependencies_is_a_no_op_when_file_does_not_exist() {
    let dir = tempfile::tempdir().expect("tempdir");
    let relative_path = Path::new("crates/example-wasm/package.json");
    let changed = migrate_wasm_package_json_vitest_dev_dependencies(dir.path(), relative_path).expect("must not error");
    assert!(!changed);
    assert!(!dir.path().join(relative_path).exists());
}

/// `migrate_wasm_package_json` is the one call site `cli::pipeline::generate::scaffold` invokes;
/// a file missing both the `exports` map and the vitest devDependencies (the true state of a
/// crate scaffolded before either fix shipped) must come out of one call with both repairs
/// applied, and a second call must be a byte-identical no-op.
#[test]
fn migrate_wasm_package_json_applies_both_repairs_through_the_one_entry_point() {
    let dir = tempfile::tempdir().expect("tempdir");
    let pkg_dir = dir.path().join("crates/example-wasm");
    std::fs::create_dir_all(&pkg_dir).expect("create crates/example-wasm");
    std::fs::write(pkg_dir.join("package.json"), pre_vitest_fix_package_json()).expect("write pre-fix package.json");
    let relative_path = Path::new("crates/example-wasm/package.json");

    let changed = migrate_wasm_package_json(dir.path(), relative_path).expect("migration must not error");
    assert!(changed, "a file missing both fixes must be reported as changed");

    let after_first = std::fs::read_to_string(pkg_dir.join("package.json")).expect("read migrated file");
    let parsed: serde_json::Value = serde_json::from_str(&after_first).expect("migrated file must be valid JSON");
    assert_eq!(
        parsed["exports"]["."]["types"], "./pkg/nodejs/example_wasm.d.ts",
        "the exports repair must have run, got:\n{parsed:#}"
    );
    assert_eq!(
        parsed["devDependencies"]["vitest"],
        tv::npm::VITEST,
        "the vitest devDependency repair must have run, got:\n{parsed:#}"
    );
    assert_eq!(
        parsed["devDependencies"]["@vitest/coverage-v8"],
        tv::npm::VITEST_COVERAGE_V8,
        "the coverage provider repair must have run, got:\n{parsed:#}"
    );

    let changed_again = migrate_wasm_package_json(dir.path(), relative_path).expect("second pass must not error");
    assert!(
        !changed_again,
        "second pass over an already-migrated file must be a no-op"
    );
    let after_second = std::fs::read_to_string(pkg_dir.join("package.json")).expect("read file after second pass");
    assert_eq!(
        after_first, after_second,
        "a second migration pass must produce byte-identical output to the first"
    );
}