Skip to main content

Abstract Class: SpecRepository

Defined in: packages/core/src/application/ports/spec-repository.ts:20

Port for reading and writing specs within a single workspace.

Extends Repository — workspace(), ownership(), and isExternal() are set at construction time and cannot change. Use cases that need multiple workspaces receive a separate instance per workspace.

list and get return lightweight Spec metadata — no artifact content is loaded. Content is fetched explicitly via artifact(). Write operations receive a Spec so implementations never deal with raw paths.

Extends​

Constructors​

Constructor​

new SpecRepository(config): SpecRepository

Defined in: packages/core/src/application/ports/spec-repository.ts:26

Creates a new SpecRepository instance.

Parameters​

config​

RepositoryConfig

Workspace, ownership, and locality configuration

Returns​

SpecRepository

Overrides​

Repository.constructor

Methods​

artifact()​

abstract artifact(spec, filename): Promise<SpecArtifact | null>

Defined in: packages/core/src/application/ports/spec-repository.ts:55

Loads the content of a single artifact file within a spec.

Parameters​

spec​

Spec

The spec containing the artifact

filename​

string

The artifact filename to load (e.g. "spec.md")

Returns​

Promise<SpecArtifact | null>

The artifact with its content, or null if the file does not exist


configPath()​

configPath(): string

Defined in: packages/core/src/application/ports/repository.ts:88

Returns the absolute path to the config directory.

Returns​

string

The config path (e.g. /project/.specd/config)

Inherited from​

Repository.configPath


delete()​

abstract delete(spec): Promise<void>

Defined in: packages/core/src/application/ports/spec-repository.ts:80

Deletes the entire spec directory and all its artifact files.

Parameters​

spec​

Spec

The spec to delete

Returns​

Promise<void>


get()​

abstract get(name): Promise<Spec | null>

Defined in: packages/core/src/application/ports/spec-repository.ts:36

Returns the spec metadata for the given name, or null if not found.

Parameters​

name​

SpecPath

The spec identity path within this workspace (e.g. auth/oauth)

Returns​

Promise<Spec | null>

The spec metadata, or null if no such spec exists


isExternal()​

isExternal(): boolean

Defined in: packages/core/src/application/ports/repository.ts:79

Returns whether this repository points to data outside the current git repository.

Returns​

boolean

true if this repository is external to the current git root

Inherited from​

Repository.isExternal


list()​

abstract list(prefix?): Promise<Spec[]>

Defined in: packages/core/src/application/ports/spec-repository.ts:46

Lists all spec metadata in this workspace, optionally filtered by a path prefix.

Returns lightweight Spec objects — no artifact content is loaded.

Parameters​

prefix?​

SpecPath

Optional path prefix to filter results (e.g. auth returns all auth/*)

Returns​

Promise<Spec[]>

All matching specs, in repository order


metadata()​

abstract metadata(spec): Promise<SpecMetadata | null>

Defined in: packages/core/src/application/ports/spec-repository.ts:92

Returns the parsed metadata for the given spec, or null if no metadata file exists.

The returned object includes an originalHash field (SHA-256 of the raw file content) for use in conflict detection when saving.

Parameters​

spec​

Spec

The spec whose metadata to load

Returns​

Promise<SpecMetadata | null>

Parsed metadata with originalHash, or null if absent


ownership()​

ownership(): "owned" | "shared" | "readOnly"

Defined in: packages/core/src/application/ports/repository.ts:70

Returns the ownership level of this repository, as declared in specd.yaml.

Returns​

"owned" | "shared" | "readOnly"

The ownership level

Inherited from​

Repository.ownership


resolveFromPath()​

abstract resolveFromPath(inputPath, from?): Promise<ResolveFromPathResult | null>

Defined in: packages/core/src/application/ports/spec-repository.ts:132

Resolves a storage path to a spec identity within this workspace.

Accepts both absolute paths and relative spec links. When inputPath is relative (e.g. ../storage/spec.md), from must be provided as the reference spec. Relative resolution is pure computation (no I/O); absolute resolution may require filesystem access.

Returns one of:

  • { specPath, specId } — resolved within this workspace
  • { crossWorkspaceHint } — relative path escaped this workspace; the caller should try other repositories with the hint segments
  • null — not a valid spec link

Parameters​

inputPath​

string

Absolute path or relative spec link (e.g. ../storage/spec.md)

from?​

SpecPath

Reference spec for relative resolution (required when inputPath is relative)

Returns​

Promise<ResolveFromPathResult | null>

The resolved result, a cross-workspace hint, or null


save()​

abstract save(spec, artifact, options?): Promise<void>

Defined in: packages/core/src/application/ports/spec-repository.ts:73

Persists a single artifact file within a spec.

Creates the spec directory if it does not exist.

If artifact.originalHash is set and does not match the current file on disk, the save is rejected with ArtifactConflictError to prevent silently overwriting concurrent changes. Pass { force: true } to overwrite regardless.

Parameters​

spec​

Spec

The spec to write the artifact into

artifact​

SpecArtifact

The artifact to save (filename + content)

options?​

Save options

force?​

boolean

When true, skip conflict detection and overwrite unconditionally

Returns​

Promise<void>

Throws​

When a concurrent modification is detected and force is not set


saveMetadata()​

abstract saveMetadata(spec, content, options?): Promise<void>

Defined in: packages/core/src/application/ports/spec-repository.ts:108

Persists raw YAML metadata content for a spec.

Creates the metadata directory if it does not exist. When originalHash is provided and force is not true, the current file on disk is hashed and compared — a mismatch causes ArtifactConflictError.

Parameters​

spec​

Spec

The spec to write metadata for

content​

string

Raw YAML string to persist

options?​

Save options

force?​

boolean

Skip conflict detection when true

originalHash?​

string

Expected hash of the current file on disk

Returns​

Promise<void>

Throws​

On hash mismatch when force is not set


workspace()​

workspace(): string

Defined in: packages/core/src/application/ports/repository.ts:61

Returns the workspace name this repository is bound to.

Returns​

string

The workspace name (e.g. "billing", "default")

Inherited from​

Repository.workspace