Aquesta és una versió anterior. La versió actual és la 0.45.0. Vayu 0.45.0 · Data de publicació:
Fitxers d’instal·lació 0.24.0
| Arquitectura | Tipus | Àmbit | Mida del fitxer | Baixa | SHA256 |
|---|---|---|---|---|---|
| 64 bits | EXE (NSIS) · en-US | — | — | github.com | VirusTotal |
L’enllaç i l’SHA256 provenen del manifest comunitari del Gestor de paquets del Windows. Convé comparar el hash del fitxer baixat abans d’executar-lo.
Notes de la versió
0.24.0 - 2026-08-29
The compatibility and durability release. Three threads run through it. The pm.* scripting surface stopped being a subset and became the API imported collections actually reach for: pm.request.url and pm.request.body are Postman's own Url and RequestBody objects, pm.sendRequest composes auth and resolves {{variables}}, chai's language chains read as English, and the dynamic-variable table went from 15 names to 39. A load run now has an identity - {{$vu}}, {{$iteration}} and a {{$guid}} family that regenerates per iteration rather than being frozen at composition - so a data-driven run varies on three axes instead of one. And the workspace stopped being a single file with nothing standing behind it: deletes are soft and restorable, POST /workspace/backup writes a snapshot you control, a corrupt database is quarantined rather than destroyed, and the log directory is bounded on all three of the axes it used to grow on. The bulk of the change is engine C++; the app carries the Trash drawer, the undo, and every surface that had to learn the two new reserved namespaces.
Added
- A Trash, with restore, undo and a retention window. Deleting a collection was irreversible with a confirm dialog as the whole safety net. DELETE /collections/:id and DELETE /requests/:id now stamp a nullable deleted_at instead of removing rows - a collection's cascade stamps its subtree in one transaction - and every read surface filters stamped rows out, so the tree each client sees is the one a hard cascade would have left. GET /trash lists the deleted roots with what their cascade took along, POST /trash/:id/restore clears the stamp, DELETE /trash/:id is the old hard cascade asked for deliberately, and a startup sweep purges anything older than trashRetentionDays (default 30; 0 keeps the trash forever). Two rules make a restore precise: one delete stamps its subtree with one timestamp and a restore clears exactly that timestamp, so restoring a collection cannot resurrect a request deleted separately beforehand; and a restored collection whose parent is gone comes back at the tree root, while a request whose collection is still in the trash is a 409 naming the collection to restore first. The app gets a sixth drawer view over it - cascade counts, because a folder in the trash is otherwise indistinguishable from an empty one, and a retention sentence read from the setting rather than written into the copy. The delete toast now offers the undo the dialog always implied, and the undo gives back what a restore alone cannot: the focused tab that was closed and the collection's remembered data-file path, both captured in the closure before the mutation runs. MCP closes the same loop with list_trash, restore_trash_entry and purge_trash_entry, the purge double-gated exactly like delete_collection.
- On-demand workspace backups. Everything a Vayu user builds lives in one SQLite file and there was no copy of it they controlled - the .bak the constructor writes is rewritten on every clean start, and copying the file by hand while the engine runs is unsafe under WAL. POST /workspace/backup (with a CLI verb beside it) writes one snapshot into backups/ with SQLite's VACUUM INTO: consistent under WAL, compacted, and on a connection of its own so a large copy does not park every other endpoint behind it. Names are UTC and fixed-width, so retention sorts them as text rather than trusting an mtime; the newest maxBackupsRetained (default 5) are kept and only files matching that name are ever removed, so a copy you put in the directory survives. A second concurrent backup is refused with 409 through a single RAII-held slot. Restoring is a file copy you perform yourself, which is why the response's whole point is the path.
- A load run carries an identity: {{$vu}} and {{$iteration}}. Which virtual user this request belongs to (1-based) and which of that user's iterations it is (0-based). They are reserved names rather than variables - a variable of either name does not answer for them - and they are substituted immediately before each send, so every iteration carries its own numbers. Neither needs a data file, because the identity comes from the iteration and not from a row. Scripts read them through pm.variables.replaceIn("{{$vu}}") and through pm.info.vu / .iteration, and a credential defers for the token it carries rather than for the rows the run has, so user-{{$vu}} binds inside a basic-auth username even on a run with no file at all.
- The {{$guid}} family generates per iteration. A run's request is composed once and then repeated, so a generator used to be frozen into every iteration's payload. The generator names are now left written as they stand and a fresh value is produced per occurrence immediately before each send: two {{$guid}} in one body are two different ids, on every iteration. A plain Send still generates at composition, because it composes once and sends once.
- The 24 Postman generators imported collections reach for. The dynamic-variable table shipped 15 names against Postman's ~120, so an imported collection writing {{$randomCity}} sent that literal text. This adds the high-usage tier, with every shape taken from Postman's own documented example as the contract, and the engine table, the renderer's mirror and the conformance fixture pinned in lockstep so the two implementations cannot drift on what a value looks like. Two deliberate omissions are named in the docs rather than left to be rediscovered.
- pm.request.url is Postman's Url object, and pm.request.body its RequestBody. protocol, host, port, path, hash and query with getHost(), getPath(), getQueryString() and update(), and member mutation that reaches the send. The body object answers Postman's mode - including graphql - while still behaving as the string it used to be everywhere a script treated it as one.
- pm.sendRequest composes auth and resolves {{variables}}. A request sent from a script went out with its auth unapplied and its tokens unresolved; both now run through the same composition the request beside it uses, header names included.
- The rest of the pm surface, filled in. pm.test hands a done to a callback that declares one and returns pm so calls chain; pm.expect.fail([message]) exists and aborts outside a test as an assertion; the cookie API gains getAll, Date expiries and cookie-bearing callbacks; header objects gain the read half of Postman's PropertyList (each, all, count, toObject, one, indexOf); six response assertions now give chai-postman's verdict; and chai's language chains (that, which, is, has, been, with, does, but, also, of, same, still) read as English and assert nothing, instead of failing a script on its own prose. any, own and itself deliberately keep throwing by name, because each changes what the matcher after it asserts.
- A pre-request script's writes reach the same send. The canonical imported auth pattern - fetch a token, pm.environment.set("token", ...), send Bearer {{token}} - carried the previous run's token, or "" on the first, and said nothing about it. Composition still runs before the script and is still the only place a payload is composed; what changed is narrower: a name composition could not answer now keeps its braces, so exactly those are resolved once more between the script and the send. Every value composition did answer is finished text and is never revisited.
- A bound data row answers bare column names. {{email}} resolves from the row where {{data.email}} already did, outranking the environment, and the app knows it: pm.variables completion, the script chips, the collection script tab's column tones, replaceIn completion, and the request builder's preview - which now resolves against the row a Send will actually bind, instead of showing the environment's value for a name the send answers from the file.
- pm.execution.setNextRequest takes request ids and the string "null", beside the names and null it already took.
- The load dialog pre-fills the declared data file. A user who had declared a file on a collection's Data tab picked it again by hand for every load run of a request in that collection, while the same file pre-filled a collection run one dialog over. The four rules that behaviour had learned were lifted into one hook rather than copied.
Changed
- pm.response.status is the reason phrase, not the code. Postman splits the status line in two - code is the number, status is the phrase - and Vayu spelled both as the number, so a lifted script read the split wrong in silence: if (res.status === 'OK') was always false and its guard was skipped. Both objects that carry a status moved together, because two objects called a response inside one sandbox must not disagree about what status means. Scripts that compared pm.response.status to a number need pm.response.code.
- An unresolved {{name}} stays literal, and a value holding tokens resolves through them. An unknown ordinary name used to resolve to "", so https://{{host}}/x composed as https:///x - not a request that failed, a different request, sent silently. The token now reaches the wire, where DNS or the server answers with the name that was never set; a definition that exists and holds an empty value still substitutes empty, because the rule is about a name nothing answers. And baseUrl = "{{protocol}}://{{host}}" - the shape most imported Postman environments are written in - now resolves through the layers instead of composing as literal braces.