Repository navigation
Adopting Existing Code
You don't have to start from specs. openarc extract turns functions you already have into OpenArc regions without changing a byte of their bodies.
npx openarc extract src/text-utils.ts # every exported function in the file
npx openarc extract src/text-utils.ts --function slug # one function (exported or not)
npx openarc extract src/text-utils.ts --function slug --id text.makeSlugSince 0.9.0 the default output is code-first (see Code First): the markers go inside the body, the JSDoc gets an @arc id, and no spec statement is added. Given
/** Adds two numbers. */
export function add(a: number, b: number): number {
return a + b;
}in src/text-utils.ts, extract produces
/**
* Adds two numbers.
* @arc id textUtils.add
*/
export function add(a: number, b: number): number {
// @openarc:begin textUtils.add
return a + b;
// @openarc:end textUtils.add
}plus a developer-owned manifest entry. The JSDoc is the intent; add arc.test cases for its behaviour, then openarc release textUtils.add when the compiler may regenerate it. Generic functions are fine in this form. The function (or its const) must declare its return type, since the signature is the contract. A body must be a block whose braces end and start their own lines (function f() { return 1; } on one line is refused); class methods are not extracted yet.
npx openarc extract src/text-utils.ts --style region writes the earlier form. Given
/** Adds two numbers. */
export function add(a: number, b: number): number {
return a + b;
}extract produces
import * as arc from "open-arc";
type AddFn = (a: number, b: number) => number;
export const addSpec = arc.defineRegion<AddFn>({
id: "textUtils.add",
intent: ["[inferred] Adds two numbers."],
examples: [],
});
/** Adds two numbers. */
// @openarc:begin textUtils.add
export function add(a: number, b: number): number {
return a + b;
}
// @openarc:end textUtils.add-
type AddFnis printed by the TypeScript checker from the function's real signature. -
The id defaults to
<file-stem>.<functionName>, normalised to the id grammar (text-utilsbecomestextUtils). Use--id(with--function) to choose one. -
The intent is the first JSDoc line, or
TODO describe. The[inferred]prefix marks it for your review. - The JSDoc stays above the markers, so it survives a later regeneration.
-
The manifest records the region as
developer, withprovenance.source: "extracted". OpenArc never writes to developer regions, so nothing is regenerated.
The file and the manifest are written in one transaction. Running extract again is a no-op: functions already inside a region are skipped.
This works the same for both extraction styles.
- Review the intent. For a
defineRegionregion (--style region), drop the[inferred]prefix; for a code-first region, the intent is its JSDoc. - Add tests:
examplesfor adefineRegionregion,arc.testcases (orexamplesthrougharc.configure) for a code-first one. They are the only thing that lets the compiler regenerate the region safely.releasedoes not check for them: a region with none is regenerated with tsc and the static rules as its only checks. - Run
openarc release <id>. The current body is backed up to.openarc/backup/, and the nextopenarc compilegenerates and verifies a new one.
If you edit the spec but keep the hand-written body, the region is a developer region whose spec changed, so the next compile reports OARC-E061. Run openarc resolve <id> --keep to accept it.
extract exits 1 with a message, and writes nothing for that function, when it finds:
| Case | Why |
|---|---|
| overloaded functions | a region holds one declaration with one call signature |
(--style region) generic functions |
defineRegion<F> needs a non-generic F
|
export default function () {} and other anonymous default exports |
a region needs a name; give it one first |
| class methods | regions are top-level functions (§3.2); move the logic out of the class |
| a declaration sharing a line with other code | markers need whole lines |
(--style code) no explicit return type, on the function or its const
|
the signature is the region's contract; an inferred one would follow whatever body the compiler writes |
(--style code) a body whose braces share a line with code |
the markers go on their own lines just inside the braces |
| an invalid or already-used id | ids are unique (§2.3) |
| a result that type-checks worse than the original | e.g. a package.json without "type": "module", where the added import is a TS1295 error |
Files must be under src/, where OpenArc looks for regions.