dxcomplete 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/.env.example +0 -7
  2. package/README.md +18 -54
  3. package/dist/cli.js +0 -22
  4. package/dist/validate.js +10 -26
  5. package/docs/model.md +3 -3
  6. package/docs/taxonomy.md +1 -1
  7. package/package.json +23 -23
  8. package/templates/process/README.md +1 -1
  9. package/dist/http/service.d.ts +0 -7
  10. package/dist/http/service.js +0 -725
  11. package/dist/mcp/docs.d.ts +0 -114
  12. package/dist/mcp/docs.js +0 -626
  13. package/dist/mcp/server.d.ts +0 -20
  14. package/dist/mcp/server.js +0 -3059
  15. package/dist/runtime/auth.d.ts +0 -162
  16. package/dist/runtime/auth.js +0 -394
  17. package/dist/runtime/check.d.ts +0 -7
  18. package/dist/runtime/check.js +0 -16
  19. package/dist/runtime/config.d.ts +0 -17
  20. package/dist/runtime/config.js +0 -93
  21. package/dist/runtime/mongo.d.ts +0 -9
  22. package/dist/runtime/mongo.js +0 -56
  23. package/dist/runtime/records.d.ts +0 -427
  24. package/dist/runtime/records.js +0 -2092
  25. package/scripts/check-env-surface.mjs +0 -136
  26. package/scripts/check-public-copy.mjs +0 -263
  27. package/scripts/check-service-boundary.mjs +0 -63
  28. package/scripts/dogfood-work-order.mjs +0 -506
  29. package/scripts/smoke-mcp-http.mjs +0 -4026
  30. package/src/cli.ts +0 -268
  31. package/src/http/server.ts +0 -314
  32. package/src/http/service.ts +0 -934
  33. package/src/init.ts +0 -262
  34. package/src/install-manifest.ts +0 -144
  35. package/src/mcp/docs.ts +0 -777
  36. package/src/mcp/server.ts +0 -4580
  37. package/src/package-root.ts +0 -31
  38. package/src/runtime/actor.ts +0 -61
  39. package/src/runtime/auth.ts +0 -673
  40. package/src/runtime/check.ts +0 -18
  41. package/src/runtime/config.ts +0 -128
  42. package/src/runtime/mongo.ts +0 -89
  43. package/src/runtime/records.ts +0 -3205
  44. package/src/runtime/workspace.ts +0 -155
  45. package/src/upgrade.ts +0 -356
  46. package/src/validate.ts +0 -141
  47. package/src/version.ts +0 -16
package/src/init.ts DELETED
@@ -1,262 +0,0 @@
1
- import { copyFile, mkdir, readdir, writeFile } from "node:fs/promises";
2
- import path from "node:path";
3
- import { INSTALL_MANIFEST_PATH, writeInstallManifest } from "./install-manifest.js";
4
- import { fileExists, resolvePackageRoot } from "./package-root.js";
5
- import { getUpgradeManagedFiles } from "./upgrade.js";
6
-
7
- export type InitOptions = {
8
- targetDir: string;
9
- force?: boolean;
10
- dryRun?: boolean;
11
- includeGithubWorkflow?: boolean;
12
- };
13
-
14
- export type InitResult = {
15
- targetDir: string;
16
- written: string[];
17
- skipped: string[];
18
- planned: string[];
19
- };
20
-
21
- type CopyOptions = Required<Pick<InitOptions, "force" | "dryRun">>;
22
-
23
- export async function initProject(options: InitOptions): Promise<InitResult> {
24
- const targetDir = path.resolve(options.targetDir);
25
- const force = options.force ?? false;
26
- const dryRun = options.dryRun ?? false;
27
- const includeGithubWorkflow = options.includeGithubWorkflow ?? true;
28
- const packageRoot = await resolvePackageRoot();
29
-
30
- const result: InitResult = {
31
- targetDir,
32
- written: [],
33
- skipped: [],
34
- planned: []
35
- };
36
-
37
- await copyDirectory(
38
- path.join(packageRoot, "docs"),
39
- path.join(targetDir, "dxcomplete", "docs"),
40
- { force, dryRun },
41
- result
42
- );
43
-
44
- await copyDirectory(
45
- path.join(packageRoot, "templates", "process"),
46
- path.join(targetDir, "dxcomplete", "process"),
47
- { force, dryRun },
48
- result
49
- );
50
-
51
- await writeWorkspaceConfig(targetDir, { force, dryRun }, result);
52
-
53
- await copyFileIfAbsent(
54
- path.join(packageRoot, "templates", "AGENTS.md"),
55
- path.join(targetDir, "AGENTS.md"),
56
- { dryRun },
57
- result
58
- );
59
-
60
- await copyDirectory(
61
- path.join(packageRoot, "templates", "next", "pages"),
62
- path.join(targetDir, "pages"),
63
- { force, dryRun },
64
- result
65
- );
66
-
67
- await copyFileIfAvailable(
68
- path.join(packageRoot, "templates", "next", "vercel.json"),
69
- path.join(targetDir, "vercel.json"),
70
- { force, dryRun },
71
- result
72
- );
73
-
74
- if (includeGithubWorkflow) {
75
- await copyDirectory(
76
- path.join(packageRoot, "templates", "github", "workflows"),
77
- path.join(targetDir, ".github", "workflows"),
78
- { force, dryRun },
79
- result
80
- );
81
- }
82
-
83
- await writeScaffoldManifest(packageRoot, targetDir, { force, dryRun }, result);
84
-
85
- return result;
86
- }
87
-
88
- async function writeScaffoldManifest(
89
- packageRoot: string,
90
- targetDir: string,
91
- options: CopyOptions,
92
- result: InitResult
93
- ): Promise<void> {
94
- const managedFiles = getUpgradeManagedFiles(packageRoot, targetDir);
95
- const managedDestinations = new Set(managedFiles.map((file) => file.destinationRelative));
96
- const skippedManagedFile = result.skipped.some((file) => managedDestinations.has(file));
97
-
98
- if (skippedManagedFile && !options.force) {
99
- result.skipped.push(INSTALL_MANIFEST_PATH);
100
- return;
101
- }
102
-
103
- if (options.dryRun) {
104
- result.planned.push(INSTALL_MANIFEST_PATH);
105
- return;
106
- }
107
-
108
- await writeInstallManifest(targetDir, managedFiles);
109
- result.written.push(INSTALL_MANIFEST_PATH);
110
- }
111
-
112
- async function copyFileIfAvailable(
113
- sourcePath: string,
114
- destinationPath: string,
115
- options: CopyOptions,
116
- result: InitResult
117
- ): Promise<void> {
118
- if (!(await fileExists(sourcePath))) {
119
- return;
120
- }
121
-
122
- const relativeDestination = path.relative(result.targetDir, destinationPath);
123
- const exists = await fileExists(destinationPath);
124
-
125
- if (exists && !options.force) {
126
- result.skipped.push(relativeDestination);
127
- return;
128
- }
129
-
130
- if (options.dryRun) {
131
- result.planned.push(relativeDestination);
132
- return;
133
- }
134
-
135
- await mkdir(path.dirname(destinationPath), { recursive: true });
136
- await copyFile(sourcePath, destinationPath);
137
- result.written.push(relativeDestination);
138
- }
139
-
140
- async function copyFileIfAbsent(
141
- sourcePath: string,
142
- destinationPath: string,
143
- options: Pick<CopyOptions, "dryRun">,
144
- result: InitResult
145
- ): Promise<void> {
146
- if (!(await fileExists(sourcePath))) {
147
- return;
148
- }
149
-
150
- const relativeDestination = path.relative(result.targetDir, destinationPath);
151
- const exists = await fileExists(destinationPath);
152
-
153
- if (exists) {
154
- result.skipped.push(relativeDestination);
155
- return;
156
- }
157
-
158
- if (options.dryRun) {
159
- result.planned.push(relativeDestination);
160
- return;
161
- }
162
-
163
- await mkdir(path.dirname(destinationPath), { recursive: true });
164
- await copyFile(sourcePath, destinationPath);
165
- result.written.push(relativeDestination);
166
- }
167
-
168
- async function writeWorkspaceConfig(
169
- targetDir: string,
170
- options: CopyOptions,
171
- result: InitResult
172
- ): Promise<void> {
173
- const destinationPath = path.join(targetDir, "dxcomplete", "workspace.json");
174
- const relativeDestination = path.relative(result.targetDir, destinationPath);
175
- const exists = await fileExists(destinationPath);
176
-
177
- if (exists && !options.force) {
178
- result.skipped.push(relativeDestination);
179
- return;
180
- }
181
-
182
- if (options.dryRun) {
183
- result.planned.push(relativeDestination);
184
- return;
185
- }
186
-
187
- const workspaceId = slugifyWorkspaceId(path.basename(targetDir)) || "dxcomplete-workspace";
188
- const workspaceName = titleizeWorkspaceName(path.basename(targetDir)) || "DX Complete Workspace";
189
- const content = `${JSON.stringify(
190
- {
191
- workspaceId,
192
- name: workspaceName,
193
- bootstrapMembers: []
194
- },
195
- null,
196
- 2
197
- )}\n`;
198
-
199
- await mkdir(path.dirname(destinationPath), { recursive: true });
200
- await writeFile(destinationPath, content, "utf8");
201
- result.written.push(relativeDestination);
202
- }
203
-
204
- async function copyDirectory(
205
- sourceDir: string,
206
- destinationDir: string,
207
- options: CopyOptions,
208
- result: InitResult
209
- ): Promise<void> {
210
- const entries = await readdir(sourceDir, { withFileTypes: true });
211
-
212
- if (!options.dryRun) {
213
- await mkdir(destinationDir, { recursive: true });
214
- }
215
-
216
- for (const entry of entries) {
217
- const sourcePath = path.join(sourceDir, entry.name);
218
- const destinationPath = path.join(destinationDir, entry.name);
219
-
220
- if (entry.isDirectory()) {
221
- await copyDirectory(sourcePath, destinationPath, options, result);
222
- continue;
223
- }
224
-
225
- if (!entry.isFile()) {
226
- continue;
227
- }
228
-
229
- const relativeDestination = path.relative(result.targetDir, destinationPath);
230
- const exists = await fileExists(destinationPath);
231
-
232
- if (exists && !options.force) {
233
- result.skipped.push(relativeDestination);
234
- continue;
235
- }
236
-
237
- if (options.dryRun) {
238
- result.planned.push(relativeDestination);
239
- continue;
240
- }
241
-
242
- await mkdir(path.dirname(destinationPath), { recursive: true });
243
- await copyFile(sourcePath, destinationPath);
244
- result.written.push(relativeDestination);
245
- }
246
- }
247
-
248
- function slugifyWorkspaceId(value: string): string {
249
- return value
250
- .trim()
251
- .toLowerCase()
252
- .replace(/[^a-z0-9]+/g, "-")
253
- .replace(/^-+|-+$/g, "");
254
- }
255
-
256
- function titleizeWorkspaceName(value: string): string {
257
- return value
258
- .trim()
259
- .replace(/[-_]+/g, " ")
260
- .replace(/\s+/g, " ")
261
- .replace(/\b\w/g, (letter) => letter.toUpperCase());
262
- }
@@ -1,144 +0,0 @@
1
- import { createHash } from "node:crypto";
2
- import { mkdir, readFile, writeFile } from "node:fs/promises";
3
- import path from "node:path";
4
- import { fileExists } from "./package-root.js";
5
- import {
6
- DXCOMPLETE_PACKAGE_VERSION,
7
- WORKSPACE_COMPATIBILITY_VERSION
8
- } from "./version.js";
9
-
10
- export const INSTALL_MANIFEST_PATH = path.join("dxcomplete", ".install-manifest.json");
11
- export const INSTALL_MANIFEST_SCHEMA_VERSION = 1;
12
-
13
- export type UpgradeManagedFile = {
14
- destinationRelative: string;
15
- sourceRelative: string;
16
- sourcePath: string;
17
- destinationPath: string;
18
- strategy: "copy" | "merge-vercel";
19
- };
20
-
21
- export type InstallManifest = {
22
- schemaVersion: number;
23
- packageVersion: string;
24
- workspaceCompatibility: number;
25
- installedAt: string;
26
- managedFiles: Record<string, InstallManifestFile>;
27
- };
28
-
29
- export type InstallManifestFile = {
30
- sha256: string;
31
- source: string;
32
- strategy: UpgradeManagedFile["strategy"];
33
- };
34
-
35
- export async function readInstallManifest(targetDir: string): Promise<InstallManifest | undefined> {
36
- const manifestPath = path.join(targetDir, INSTALL_MANIFEST_PATH);
37
-
38
- if (!(await fileExists(manifestPath))) {
39
- return undefined;
40
- }
41
-
42
- const parsed = JSON.parse(await readFile(manifestPath, "utf8")) as unknown;
43
- return parseInstallManifest(parsed, manifestPath);
44
- }
45
-
46
- export async function writeInstallManifest(targetDir: string, files: UpgradeManagedFile[]): Promise<void> {
47
- const managedFiles: Record<string, InstallManifestFile> = {};
48
-
49
- for (const file of files) {
50
- if (!(await fileExists(file.destinationPath))) {
51
- continue;
52
- }
53
-
54
- managedFiles[file.destinationRelative] = {
55
- sha256: await hashFile(file.destinationPath),
56
- source: file.sourceRelative,
57
- strategy: file.strategy
58
- };
59
- }
60
-
61
- const manifest: InstallManifest = {
62
- schemaVersion: INSTALL_MANIFEST_SCHEMA_VERSION,
63
- packageVersion: DXCOMPLETE_PACKAGE_VERSION,
64
- workspaceCompatibility: WORKSPACE_COMPATIBILITY_VERSION,
65
- installedAt: new Date().toISOString(),
66
- managedFiles
67
- };
68
-
69
- const manifestPath = path.join(targetDir, INSTALL_MANIFEST_PATH);
70
- await mkdir(path.dirname(manifestPath), { recursive: true });
71
- await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, "utf8");
72
- }
73
-
74
- export async function hashFile(filePath: string): Promise<string> {
75
- return hashContent(await readFile(filePath));
76
- }
77
-
78
- export function hashContent(content: string | Buffer): string {
79
- return createHash("sha256").update(content).digest("hex");
80
- }
81
-
82
- function parseInstallManifest(value: unknown, source: string): InstallManifest {
83
- if (!value || typeof value !== "object") {
84
- throw new Error(`${source} must be a JSON object.`);
85
- }
86
-
87
- const input = value as Record<string, unknown>;
88
- const schemaVersion = readNumber(input.schemaVersion, "schemaVersion", source);
89
- const packageVersion = readString(input.packageVersion, "packageVersion", source);
90
- const workspaceCompatibility = readNumber(input.workspaceCompatibility, "workspaceCompatibility", source);
91
- const installedAt = readString(input.installedAt, "installedAt", source);
92
- const managedFiles = parseManagedFiles(input.managedFiles, source);
93
-
94
- return {
95
- schemaVersion,
96
- packageVersion,
97
- workspaceCompatibility,
98
- installedAt,
99
- managedFiles
100
- };
101
- }
102
-
103
- function parseManagedFiles(value: unknown, source: string): Record<string, InstallManifestFile> {
104
- if (!value || typeof value !== "object" || Array.isArray(value)) {
105
- throw new Error(`${source} managedFiles must be a JSON object.`);
106
- }
107
-
108
- const output: Record<string, InstallManifestFile> = {};
109
- for (const [filePath, fileValue] of Object.entries(value as Record<string, unknown>)) {
110
- if (!fileValue || typeof fileValue !== "object" || Array.isArray(fileValue)) {
111
- throw new Error(`${source} managedFiles.${filePath} must be a JSON object.`);
112
- }
113
-
114
- const file = fileValue as Record<string, unknown>;
115
- const strategy = readString(file.strategy, `managedFiles.${filePath}.strategy`, source);
116
- if (strategy !== "copy" && strategy !== "merge-vercel") {
117
- throw new Error(`${source} managedFiles.${filePath}.strategy must be copy or merge-vercel.`);
118
- }
119
-
120
- output[filePath] = {
121
- sha256: readString(file.sha256, `managedFiles.${filePath}.sha256`, source),
122
- source: readString(file.source, `managedFiles.${filePath}.source`, source),
123
- strategy
124
- };
125
- }
126
-
127
- return output;
128
- }
129
-
130
- function readString(value: unknown, key: string, source: string): string {
131
- if (typeof value !== "string" || !value.trim()) {
132
- throw new Error(`${source} ${key} must be a non-empty string.`);
133
- }
134
-
135
- return value;
136
- }
137
-
138
- function readNumber(value: unknown, key: string, source: string): number {
139
- if (typeof value !== "number" || !Number.isInteger(value) || value < 0) {
140
- throw new Error(`${source} ${key} must be a non-negative integer.`);
141
- }
142
-
143
- return value;
144
- }