The code editor

Most mistakes are caught before anything runs.

You write JavaScript here, and only here — a few lines on a button, a rule on a table. What makes that pleasant is not the colouring. It is that the editor has your data model in front of it and your database open, so it can tell you that customre is not a table, that this query would read a hundred thousand rows, and that this comparison can never be true — while you are typing, not when a customer phones.

It knows your data model

Every table, every field, every relationship, every object on the window you are standing in. That is the difference between an editor that colours words and one that reads them.

Completion that is about your project

Type database. and your tables are offered; type a table and its fields are. A chain is read as steps, so invoices.where(…). knows what it is holding. It is our own window rather than the system's, which is why it can show what a command does and what it gives back.

The manual, at the command under the cursor

Click the book in the completion list, or press ⌥↩, and the bundled manual opens at exactly that command — not at its front page. The anchor comes from the manual's own naming, so the two cannot drift apart.

⌘-click goes to the thing

A table name, a field, an object on the window: hold ⌘ and click, and you are there. The editor knows what the word is, so it knows where it lives.

It knows what may not be said here

A rule on a table has a record; a button on a window has a form. Writing the one in the other's script is underlined, because the editor knows which file you are in and what that file is allowed to do.

The code editor with the completion list open, showing commands from the
                project's own schema
The completion list is built from your schema and the API together — and every entry can open the manual at itself.

A misspelt name never reaches your customer

The commonest mistake in a database script is a name that is one letter wrong. It compiles, it runs, and it does nothing — and in a language without types, nothing catches it.

A misspelt field name underlined in red in the code editor, and the window it
                belongs to marked with a warning triangle in the sidebar
Underlined where it is typed, and the window it belongs to marked in the sidebar — so a fault in a script you have not opened is still visible.
The silent one is the expensive one

Writing to a field that does not exist used to be accepted without a word: the value went into an ordinary JavaScript property and was saved nowhere. A crash is noticed the same afternoon; that is noticed in three months, by somebody asking why a column is empty. It is refused now — and underlined long before it could happen.

Every complaint is a place you can click

File and line, in the console, as a button that opens the script there. The alternative is hunting through tabs, and a warning that costs a hunt is ignored the third time.

And the mark goes when the fault does

Fix the name and the underline is gone; the triangle in the sidebar goes with it. That sounds obvious and was not: the mark used to survive every edit until the script happened to run again, so a repaired fault looked exactly like an unrepaired one.

Two warnings that had to earn their place

A checker that underlines correct code is a checker nobody reads twice. Both of these were built, taken out again, and rebuilt on a stricter rule: say nothing unless you have measured.

The editor underlining a bare database.invoices.all(), with a popover saying
                that invoices holds 7,628 rows in the development database
.all() on a table the editor has counted — and the three .where(…) calls higher up the same script are left alone, because somebody has already thought about those.

“This loads everything.” The first version of this warning lasted four hours. It fired at every .all(), hit nine places in our own example project — and every one of them was right: two hundred customers are loaded whole precisely so that twenty-six thousand invoice lines are not. From the source alone, “read 200” and “read 200,000” are the same three words. It speaks now only when it has counted, above five thousand rows, with the real number in the message — and it recommends only what a selection really offers. An earlier draft of that very sentence suggested a command Neuridion has never had.

The editor underlining a comparison against a translated label, saying that
                stateChoice can only hold All, Unpaid or Overdue
A comparison that can never be true — here the German label of a choice, written by hand into a script. Followed through the variable it was put in, and through a switch as well.

“That switch can never hold this.” A choice in a segmented control is two things at once: the word a person reads and the value a script compares. Translating your application moves the first and never the second, so if (choice === "Unpaid") keeps working in every language. The developer of Neuridion asked whether that was really true and was about to write the translation into the comparison to be safe — which would have broken it in exactly the way he feared. The rule was right; nothing checked it. Now the editor names the three values the switch can actually hold.

Everything still to do, in one list

Findings are worth nothing where nobody looks for them. The checklist in the toolbar gathers what every checker knows — faults, things still to replace, things unfinished — sorted so the first row is the one that matters.

The to-do list in Neuridion, listing what is still to replace in the project
Every row is a button that takes you to the place. And an assistant can be handed the findings — never the project.
The triangle means two things, and says which

What the editor can see without running anything, and the last crash. Both on windows, application scripts and table rules alike, with the file and line under the pointer. A crash is forgotten the moment its script is edited.

A sentence that never travels

In a project with more than one language, a message your script shows without marking it for translation stays in the base language in every build. Nothing said so until this list did.

And it can mark them for you

Right-click, Mark Sentences for Translation, and every literal at a place a person reads is wrapped — one edit, one undo. A sentence built with + is handed back instead, because the placeholder names are yours to choose.

And when reading is not enough, there is a debugger

Breakpoints with conditions and hit counts, Step Over and Step Out, values you can open, a post-mortem after a throw — and the query log, which is the thing that makes a loop reading one record at a time visible at all.

The debugger paused at a breakpoint, with the variables of the current scope
                listed beside the script
Paused on real data, in the real application — Run and Debug are free for ever and need no licence.
A forgotten breakpoint refuses the build. A pause() left in a script would stop somebody else's application dead, so it is not a warning — the build does not finish until it is gone.

Carry on.

How it works

Four steps from an empty project to an application, and you write code in exactly one of them.

The manual

Every command, with a worked example — the same manual the editor opens at the word under your cursor.

How it’s made

Why these checkers are the shape they are, including the two that were removed again the day they were built.