Skip to content

Commit 8214be4

Browse files
clydinKeen Yee Liau
authored and
Keen Yee Liau
committed
docs(@angular-devkit/core): add preliminary overview of workspace API
1 parent 8a34a85 commit 8214be4

File tree

2 files changed

+150
-1
lines changed

2 files changed

+150
-1
lines changed

packages/angular_devkit/core/README.md

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,110 @@ export class CoreSchemaRegistry implements SchemaRegistry {
5656

5757
# Utils
5858

59-
# Virtual FS
59+
# Virtual FS
60+
61+
# Workspaces
62+
63+
The `workspaces` namespace provides an API for interacting with the workspace file formats.
64+
It provides an abstraction of the underlying storage format of the workspace and provides
65+
support for both reading and writing. Currently, the only supported format is the JSON-based
66+
format used by the Angular CLI. For this format, the API provides internal change tracking of values which
67+
enables fine-grained updates to the underlying storage of the workspace. This allows for the
68+
retention of existing formatting and comments.
69+
70+
A workspace is defined via the following object model. Definition collection objects are specialized
71+
Javascript `Map` objects with an additional `add` method to simplify addition and provide more localized
72+
error checking of the newly added values.
73+
74+
```ts
75+
export interface WorkspaceDefinition {
76+
readonly extensions: Record<string, JsonValue | undefined>;
77+
readonly projects: ProjectDefinitionCollection;
78+
}
79+
80+
export interface ProjectDefinition {
81+
readonly extensions: Record<string, JsonValue | undefined>;
82+
readonly targets: TargetDefinitionCollection;
83+
root: string;
84+
prefix?: string;
85+
sourceRoot?: string;
86+
}
87+
88+
export interface TargetDefinition {
89+
options?: Record<string, JsonValue | undefined>;
90+
configurations?: Record<string, Record<string, JsonValue | undefined> | undefined>;
91+
builder: string;
92+
}
93+
```
94+
95+
The API is asynchronous and has two main functions to facilitate reading, creation, and modifying
96+
a workspace: `readWorkspace` and `writeWorkspace`.
97+
98+
```ts
99+
export enum WorkspaceFormat {
100+
JSON,
101+
}
102+
```
103+
104+
```ts
105+
export function readWorkspace(
106+
path: string,
107+
host: WorkspaceHost,
108+
format?: WorkspaceFormat,
109+
): Promise<{ workspace: WorkspaceDefinition; }>;
110+
```
111+
112+
```ts
113+
export function writeWorkspace(
114+
workspace: WorkspaceDefinition,
115+
host: WorkspaceHost,
116+
path?: string,
117+
format?: WorkspaceFormat,
118+
): Promise<void>;
119+
```
120+
121+
A `WorkspaceHost` abstracts the underlying data access methods from the functions. It provides
122+
methods to read, write, and analyze paths. A utility function is provided to create
123+
an instance of a `WorkspaceHost` from the Angular DevKit's virtual filesystem host abstraction.
124+
125+
```ts
126+
export interface WorkspaceHost {
127+
readFile(path: string): Promise<string>;
128+
writeFile(path: string, data: string): Promise<void>;
129+
isDirectory(path: string): Promise<boolean>;
130+
isFile(path: string): Promise<boolean>;
131+
}
132+
133+
export function createWorkspaceHost(host: virtualFs.Host): WorkspaceHost;
134+
```
135+
136+
## Usage Example
137+
138+
To demonstrate the usage of the API, the following code will show how to add a option property
139+
to a build target for an application.
140+
141+
```ts
142+
import { NodeJsSyncHost } from '@angular-devkit/core/node';
143+
import { workspaces } from '@angular-devkit/core';
144+
145+
async function demonstrate() {
146+
const host = workspaces.createWorkspaceHost(new NodeJsSyncHost());
147+
const workspace = await workspaces.readWorkspace('path/to/workspace/directory/', host);
148+
149+
const project = workspace.projects.get('my-app');
150+
if (!project) {
151+
throw new Error('my-app does not exist');
152+
}
153+
154+
const buildTarget = project.targets.get('build');
155+
if (!buildTarget) {
156+
throw new Error('build target does not exist');
157+
}
158+
159+
buildTarget.options.optimization = true;
160+
161+
await workspaces.writeWorkspace(workspace, host);
162+
}
163+
164+
demonstrate();
165+
```

packages/angular_devkit/core/src/workspace/core.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,23 @@ import { writeJsonWorkspace } from './json/writer';
1313

1414
const formatLookup = new WeakMap<WorkspaceDefinition, WorkspaceFormat>();
1515

16+
/**
17+
* Supported workspace formats
18+
*/
1619
export enum WorkspaceFormat {
1720
JSON,
1821
}
1922

23+
/**
24+
* @private
25+
*/
2026
export function _test_addWorkspaceFile(name: string, format: WorkspaceFormat): void {
2127
workspaceFiles[name] = format;
2228
}
2329

30+
/**
31+
* @private
32+
*/
2433
export function _test_removeWorkspaceFile(name: string): void {
2534
delete workspaceFiles[name];
2635
}
@@ -31,6 +40,22 @@ const workspaceFiles: Record<string, WorkspaceFormat> = {
3140
'.angular.json': WorkspaceFormat.JSON,
3241
};
3342

43+
/**
44+
* Reads and constructs a `WorkspaceDefinition`. If the function is provided with a path to a
45+
* directory instead of a file, a search of the directory's files will commence to attempt to
46+
* locate a known workspace file. Currently the following are considered known workspace files:
47+
* - `angular.json`
48+
* - `.angular.json`
49+
*
50+
* @param path The path to either a workspace file or a directory containing a workspace file.
51+
* @param host The `WorkspaceHost` to use to access the file and directory data.
52+
* @param format An optional `WorkspaceFormat` value. Used if the path specifies a non-standard
53+
* file name that would prevent automatically discovering the format.
54+
*
55+
*
56+
* @return An `Promise` of the read result object with the `WorkspaceDefinition` contained within
57+
* the `workspace` property.
58+
*/
3459
export async function readWorkspace(
3560
path: string,
3661
host: WorkspaceHost,
@@ -82,6 +107,24 @@ export async function readWorkspace(
82107
return { workspace };
83108
}
84109

110+
/**
111+
* Writes a `WorkspaceDefinition` to the underlying storage via the provided `WorkspaceHost`.
112+
* If the `WorkspaceDefinition` was created via the `readWorkspace` function, metadata will be
113+
* used to determine the path and format of the Workspace. In all other cases, the `path` and
114+
* `format` options must be specified as they would be otherwise unknown.
115+
*
116+
* @param workspace The `WorkspaceDefinition` that will be written.
117+
* @param host The `WorkspaceHost` to use to access/write the file and directory data.
118+
* @param path The path to a file location for the output. Required if `readWorkspace` was not
119+
* used to create the `WorkspaceDefinition`. Optional otherwise; will override the
120+
* `WorkspaceDefinition` metadata if provided.
121+
* @param format The `WorkspaceFormat` to use for output. Required if `readWorkspace` was not
122+
* used to create the `WorkspaceDefinition`. Optional otherwise; will override the
123+
* `WorkspaceDefinition` metadata if provided.
124+
*
125+
*
126+
* @return An `Promise` of type `void`.
127+
*/
85128
export async function writeWorkspace(
86129
workspace: WorkspaceDefinition,
87130
host: WorkspaceHost,

0 commit comments

Comments
 (0)