dxcomplete 0.2.1 → 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 +17 -45
  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/runtime-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
@@ -1,155 +0,0 @@
1
- import { constants as fsConstants } from "node:fs";
2
- import { access, readFile } from "node:fs/promises";
3
- import path from "node:path";
4
- import { normalizeEmail } from "./actor.js";
5
-
6
- export type WorkspaceBootstrapMember = {
7
- email: string;
8
- roles: WorkspaceBootstrapRole[];
9
- role?: "owner" | "member";
10
- };
11
-
12
- export type WorkspaceConfig = {
13
- workspaceId: string;
14
- name: string;
15
- mode?: WorkspaceMode;
16
- bootstrapMembers: WorkspaceBootstrapMember[];
17
- };
18
-
19
- export type WorkspaceMode = "transformation" | "greenfield" | "limited-disclosure";
20
- export type WorkspaceBootstrapRole = "owner" | "engineer" | "tester" | "operator" | "support_agent" | "end_user";
21
-
22
- export type WorkspaceConfigOptions = {
23
- cwd?: string;
24
- configPath?: string;
25
- };
26
-
27
- const DEFAULT_WORKSPACE_CONFIG = path.join("dxcomplete", "workspace.json");
28
-
29
- export async function loadWorkspaceConfig(options: WorkspaceConfigOptions = {}): Promise<WorkspaceConfig> {
30
- const cwd = path.resolve(options.cwd ?? process.cwd());
31
- const configPath = path.resolve(cwd, options.configPath ?? DEFAULT_WORKSPACE_CONFIG);
32
-
33
- if (!(await fileExists(configPath))) {
34
- throw new Error(`DX Complete workspace config not found: ${configPath}`);
35
- }
36
-
37
- const parsed = JSON.parse(await readFile(configPath, "utf8")) as unknown;
38
- return parseWorkspaceConfig(parsed, configPath);
39
- }
40
-
41
- export function parseWorkspaceConfig(value: unknown, source = "workspace config"): WorkspaceConfig {
42
- if (!value || typeof value !== "object") {
43
- throw new Error(`${source} must be a JSON object.`);
44
- }
45
-
46
- const input = value as Record<string, unknown>;
47
- const workspaceId = readRequiredString(input.workspaceId, "workspaceId", source);
48
- const name = readRequiredString(input.name, "name", source);
49
- const mode = parseWorkspaceMode(input.mode, source);
50
- const bootstrapMembers = parseBootstrapMembers(input.bootstrapMembers, source);
51
-
52
- return {
53
- workspaceId,
54
- name,
55
- ...(mode ? { mode } : {}),
56
- bootstrapMembers
57
- };
58
- }
59
-
60
- function parseWorkspaceMode(value: unknown, source: string): WorkspaceMode | undefined {
61
- if (value === undefined) {
62
- return undefined;
63
- }
64
-
65
- if (value === "transformation" || value === "greenfield" || value === "limited-disclosure") {
66
- return value;
67
- }
68
-
69
- throw new Error(`${source} mode must be transformation, greenfield, or limited-disclosure when provided.`);
70
- }
71
-
72
- function parseBootstrapMembers(value: unknown, source: string): WorkspaceBootstrapMember[] {
73
- if (value === undefined) {
74
- return [];
75
- }
76
-
77
- if (!Array.isArray(value)) {
78
- throw new Error(`${source} bootstrapMembers must be an array when provided.`);
79
- }
80
-
81
- return value.map((entry, index) => {
82
- if (!entry || typeof entry !== "object") {
83
- throw new Error(`${source} bootstrapMembers[${index}] must be an object.`);
84
- }
85
-
86
- const record = entry as Record<string, unknown>;
87
- const email = normalizeEmail(readRequiredString(record.email, `bootstrapMembers[${index}].email`, source));
88
- const roles = parseBootstrapMemberRoles(record, `bootstrapMembers[${index}]`, source);
89
-
90
- return { email, roles };
91
- });
92
- }
93
-
94
- function parseBootstrapMemberRoles(
95
- record: Record<string, unknown>,
96
- keyPrefix: string,
97
- source: string
98
- ): WorkspaceBootstrapRole[] {
99
- if (Array.isArray(record.roles)) {
100
- const roles = record.roles.map((role, roleIndex) =>
101
- parseBootstrapRole(role, `${keyPrefix}.roles[${roleIndex}]`, source)
102
- );
103
- return uniqueRoles(roles);
104
- }
105
-
106
- if (record.role === "owner") {
107
- return ["owner"];
108
- }
109
-
110
- if (record.role === "member") {
111
- return ["end_user"];
112
- }
113
-
114
- throw new Error(`${source} ${keyPrefix}.roles must contain at least one valid workspace role.`);
115
- }
116
-
117
- function parseBootstrapRole(value: unknown, key: string, source: string): WorkspaceBootstrapRole {
118
- if (
119
- value === "owner" ||
120
- value === "engineer" ||
121
- value === "tester" ||
122
- value === "operator" ||
123
- value === "support_agent" ||
124
- value === "end_user"
125
- ) {
126
- return value;
127
- }
128
-
129
- throw new Error(`${source} ${key} must be owner, engineer, tester, operator, support_agent, or end_user.`);
130
- }
131
-
132
- function uniqueRoles(roles: WorkspaceBootstrapRole[]): WorkspaceBootstrapRole[] {
133
- const unique = [...new Set(roles)];
134
- if (unique.length === 0) {
135
- throw new Error("workspace config bootstrap member roles must contain at least one role.");
136
- }
137
- return unique.sort();
138
- }
139
-
140
- function readRequiredString(value: unknown, key: string, source: string): string {
141
- if (typeof value !== "string" || !value.trim()) {
142
- throw new Error(`${source} ${key} must be a non-empty string.`);
143
- }
144
-
145
- return value.trim();
146
- }
147
-
148
- async function fileExists(filePath: string): Promise<boolean> {
149
- try {
150
- await access(filePath, fsConstants.F_OK);
151
- return true;
152
- } catch {
153
- return false;
154
- }
155
- }
package/src/upgrade.ts DELETED
@@ -1,356 +0,0 @@
1
- import { copyFile, mkdir, readFile, readdir, writeFile } from "node:fs/promises";
2
- import path from "node:path";
3
- import {
4
- INSTALL_MANIFEST_SCHEMA_VERSION,
5
- INSTALL_MANIFEST_PATH,
6
- type InstallManifest,
7
- type UpgradeManagedFile,
8
- hashContent,
9
- hashFile,
10
- readInstallManifest,
11
- writeInstallManifest
12
- } from "./install-manifest.js";
13
- import { fileExists, resolvePackageRoot } from "./package-root.js";
14
- import {
15
- DXCOMPLETE_PACKAGE_VERSION,
16
- WORKSPACE_COMPATIBILITY_VERSION
17
- } from "./version.js";
18
-
19
- export type UpgradeOptions = {
20
- targetDir: string;
21
- apply?: boolean;
22
- force?: boolean;
23
- };
24
-
25
- export type UpgradeResult = {
26
- targetDir: string;
27
- applied: boolean;
28
- packageVersion: string;
29
- workspaceCompatibility: number;
30
- written: string[];
31
- planned: string[];
32
- unchanged: string[];
33
- manualReview: string[];
34
- userOwnedDrift: string[];
35
- manifestWritten: boolean;
36
- };
37
-
38
- const WELL_KNOWN_REWRITES = [
39
- {
40
- source: "/.well-known/oauth-authorization-server",
41
- destination: "/api/dxcomplete/.well-known/oauth-authorization-server"
42
- },
43
- {
44
- source: "/.well-known/oauth-protected-resource/api/mcp",
45
- destination: "/api/dxcomplete/.well-known/oauth-protected-resource/api/mcp"
46
- }
47
- ];
48
- const WORKSPACE_CONFIG_PATH = path.join("dxcomplete", "workspace.json");
49
-
50
- export async function upgradeProject(options: UpgradeOptions): Promise<UpgradeResult> {
51
- const targetDir = path.resolve(options.targetDir);
52
- const apply = options.apply ?? false;
53
- const force = options.force ?? false;
54
- await assertExistingDxcompleteInstall(targetDir);
55
- const packageRoot = await resolvePackageRoot();
56
- const managedFiles = getUpgradeManagedFiles(packageRoot, targetDir);
57
- const manifest = await readInstallManifest(targetDir);
58
- const result: UpgradeResult = {
59
- targetDir,
60
- applied: apply,
61
- packageVersion: DXCOMPLETE_PACKAGE_VERSION,
62
- workspaceCompatibility: WORKSPACE_COMPATIBILITY_VERSION,
63
- written: [],
64
- planned: [],
65
- unchanged: [],
66
- manualReview: [],
67
- userOwnedDrift: [],
68
- manifestWritten: false
69
- };
70
-
71
- if (apply) {
72
- const preview = await upgradeProject({ targetDir, apply: false, force });
73
- if (preview.manualReview.length > 0) {
74
- return {
75
- ...preview,
76
- applied: true,
77
- written: [],
78
- planned: [],
79
- manifestWritten: false
80
- };
81
- }
82
- }
83
-
84
- for (const file of managedFiles) {
85
- if (file.strategy === "merge-vercel") {
86
- await upgradeVercelConfig(file, { apply, force, manifest }, result);
87
- continue;
88
- }
89
-
90
- await upgradeCopiedFile(file, { apply, force, manifest }, result);
91
- }
92
-
93
- result.userOwnedDrift.push(...(await collectUserOwnedDrift(packageRoot, targetDir)));
94
-
95
- const manifestNeedsWrite =
96
- result.planned.length > 0 || result.written.length > 0 || shouldWriteManifest(manifest, managedFiles);
97
-
98
- if (apply && result.manualReview.length === 0 && manifestNeedsWrite) {
99
- await writeInstallManifest(targetDir, managedFiles);
100
- result.written.push(INSTALL_MANIFEST_PATH);
101
- result.manifestWritten = true;
102
- } else if (!apply && manifestNeedsWrite) {
103
- result.planned.push(INSTALL_MANIFEST_PATH);
104
- }
105
-
106
- return result;
107
- }
108
-
109
- async function assertExistingDxcompleteInstall(targetDir: string): Promise<void> {
110
- if (await fileExists(path.join(targetDir, WORKSPACE_CONFIG_PATH))) {
111
- return;
112
- }
113
-
114
- throw new Error(
115
- `DX Complete install not found in ${targetDir}. Run dxcomplete init before dxcomplete upgrade.`
116
- );
117
- }
118
-
119
- function shouldWriteManifest(manifest: InstallManifest | undefined, files: UpgradeManagedFile[]): boolean {
120
- if (!manifest) {
121
- return true;
122
- }
123
-
124
- if (
125
- manifest.schemaVersion !== INSTALL_MANIFEST_SCHEMA_VERSION ||
126
- manifest.packageVersion !== DXCOMPLETE_PACKAGE_VERSION ||
127
- manifest.workspaceCompatibility !== WORKSPACE_COMPATIBILITY_VERSION
128
- ) {
129
- return true;
130
- }
131
-
132
- return files.some((file) => !manifest.managedFiles[file.destinationRelative]);
133
- }
134
-
135
- export function getUpgradeManagedFiles(packageRoot: string, targetDir: string): UpgradeManagedFile[] {
136
- const files = [
137
- {
138
- sourceRelative: path.join("templates", "next", "pages", "api", "mcp.js"),
139
- destinationRelative: path.join("pages", "api", "mcp.js"),
140
- strategy: "copy" as const
141
- },
142
- {
143
- sourceRelative: path.join("templates", "next", "pages", "api", "dxcomplete.js"),
144
- destinationRelative: path.join("pages", "api", "dxcomplete.js"),
145
- strategy: "copy" as const
146
- },
147
- {
148
- sourceRelative: path.join("templates", "next", "pages", "api", "dxcomplete", "[...path].js"),
149
- destinationRelative: path.join("pages", "api", "dxcomplete", "[...path].js"),
150
- strategy: "copy" as const
151
- },
152
- {
153
- sourceRelative: path.join("templates", "next", "pages", "api", "auth", "callback", "google.js"),
154
- destinationRelative: path.join("pages", "api", "auth", "callback", "google.js"),
155
- strategy: "copy" as const
156
- },
157
- {
158
- sourceRelative: path.join("templates", "next", "vercel.json"),
159
- destinationRelative: "vercel.json",
160
- strategy: "merge-vercel" as const
161
- }
162
- ];
163
-
164
- return files.map((file) => ({
165
- ...file,
166
- sourcePath: path.join(packageRoot, file.sourceRelative),
167
- destinationPath: path.join(targetDir, file.destinationRelative)
168
- }));
169
- }
170
-
171
- async function upgradeCopiedFile(
172
- file: UpgradeManagedFile,
173
- options: {
174
- apply: boolean;
175
- force: boolean;
176
- manifest: InstallManifest | undefined;
177
- },
178
- result: UpgradeResult
179
- ): Promise<void> {
180
- const desiredHash = await hashFile(file.sourcePath);
181
- const exists = await fileExists(file.destinationPath);
182
- const currentHash = exists ? await hashFile(file.destinationPath) : undefined;
183
-
184
- if (currentHash === desiredHash) {
185
- result.unchanged.push(file.destinationRelative);
186
- return;
187
- }
188
-
189
- const previousHash = options.manifest?.managedFiles[file.destinationRelative]?.sha256;
190
- if (exists && !options.force && currentHash !== previousHash) {
191
- result.manualReview.push(
192
- previousHash
193
- ? `${file.destinationRelative} (modified since last DX Complete install)`
194
- : `${file.destinationRelative} (differs from the current scaffold and no install manifest is available)`
195
- );
196
- return;
197
- }
198
-
199
- if (!options.apply) {
200
- result.planned.push(file.destinationRelative);
201
- return;
202
- }
203
-
204
- await mkdir(path.dirname(file.destinationPath), { recursive: true });
205
- await copyFile(file.sourcePath, file.destinationPath);
206
- result.written.push(file.destinationRelative);
207
- }
208
-
209
- async function upgradeVercelConfig(
210
- file: UpgradeManagedFile,
211
- options: {
212
- apply: boolean;
213
- force: boolean;
214
- manifest: InstallManifest | undefined;
215
- },
216
- result: UpgradeResult
217
- ): Promise<void> {
218
- const exists = await fileExists(file.destinationPath);
219
- const templateContent = await readFile(file.sourcePath, "utf8");
220
- let desiredContent = templateContent;
221
-
222
- if (exists) {
223
- const currentContent = await readFile(file.destinationPath, "utf8");
224
- try {
225
- desiredContent = `${JSON.stringify(mergeVercelConfig(JSON.parse(currentContent)), null, 2)}\n`;
226
- } catch {
227
- if (!options.force) {
228
- result.manualReview.push(`${file.destinationRelative} (invalid JSON; cannot merge safely)`);
229
- return;
230
- }
231
- }
232
-
233
- if (hashContent(currentContent) === hashContent(desiredContent)) {
234
- result.unchanged.push(file.destinationRelative);
235
- return;
236
- }
237
- }
238
-
239
- if (!options.apply) {
240
- result.planned.push(file.destinationRelative);
241
- return;
242
- }
243
-
244
- await writeFile(file.destinationPath, desiredContent, "utf8");
245
- result.written.push(file.destinationRelative);
246
- }
247
-
248
- function mergeVercelConfig(value: unknown): Record<string, unknown> {
249
- const config = isPlainObject(value) ? { ...value } : {};
250
- const functions = isPlainObject(config.functions) ? { ...config.functions } : {};
251
- const pagesFunctionKey = "pages/api/**/*.js";
252
- const pagesFunction = isPlainObject(functions[pagesFunctionKey])
253
- ? { ...functions[pagesFunctionKey] }
254
- : {};
255
-
256
- pagesFunction.includeFiles = mergeIncludeFiles(pagesFunction.includeFiles, "dxcomplete/workspace.json");
257
- functions[pagesFunctionKey] = pagesFunction;
258
- config.functions = functions;
259
- config.rewrites = mergeRewrites(config.rewrites);
260
-
261
- return config;
262
- }
263
-
264
- function mergeIncludeFiles(value: unknown, requiredFile: string): string | string[] {
265
- if (typeof value === "string") {
266
- return value === requiredFile ? value : uniqueStrings([value, requiredFile]);
267
- }
268
-
269
- if (Array.isArray(value)) {
270
- return uniqueStrings([...value.filter((entry): entry is string => typeof entry === "string"), requiredFile]);
271
- }
272
-
273
- return requiredFile;
274
- }
275
-
276
- function mergeRewrites(value: unknown): Record<string, unknown>[] {
277
- const rewrites = Array.isArray(value)
278
- ? value.filter((entry): entry is Record<string, unknown> => isPlainObject(entry)).map((entry) => ({ ...entry }))
279
- : [];
280
-
281
- for (const requiredRewrite of WELL_KNOWN_REWRITES) {
282
- const existing = rewrites.find((rewrite) => rewrite.source === requiredRewrite.source);
283
- if (existing) {
284
- existing.destination = requiredRewrite.destination;
285
- } else {
286
- rewrites.push({ ...requiredRewrite });
287
- }
288
- }
289
-
290
- return rewrites;
291
- }
292
-
293
- async function collectUserOwnedDrift(packageRoot: string, targetDir: string): Promise<string[]> {
294
- const files = [
295
- ...(await collectTemplateFiles(
296
- path.join(packageRoot, "docs"),
297
- path.join(targetDir, "dxcomplete", "docs"),
298
- path.join("dxcomplete", "docs")
299
- )),
300
- ...(await collectTemplateFiles(
301
- path.join(packageRoot, "templates", "process"),
302
- path.join(targetDir, "dxcomplete", "process"),
303
- path.join("dxcomplete", "process")
304
- ))
305
- ];
306
- const drift: string[] = [];
307
-
308
- for (const file of files) {
309
- if (!(await fileExists(file.destinationPath))) {
310
- drift.push(`${file.destinationRelative} (missing user-owned scaffold file)`);
311
- continue;
312
- }
313
-
314
- if ((await hashFile(file.sourcePath)) !== (await hashFile(file.destinationPath))) {
315
- drift.push(`${file.destinationRelative} (differs from current package template)`);
316
- }
317
- }
318
-
319
- return drift;
320
- }
321
-
322
- async function collectTemplateFiles(
323
- sourceDir: string,
324
- destinationDir: string,
325
- destinationRootRelative: string
326
- ): Promise<Array<{ sourcePath: string; destinationPath: string; destinationRelative: string }>> {
327
- const entries = await readdir(sourceDir, { withFileTypes: true });
328
- const files: Array<{ sourcePath: string; destinationPath: string; destinationRelative: string }> = [];
329
-
330
- for (const entry of entries) {
331
- const sourcePath = path.join(sourceDir, entry.name);
332
- const destinationPath = path.join(destinationDir, entry.name);
333
- const destinationRelative = path.join(destinationRootRelative, entry.name);
334
-
335
- if (entry.isDirectory()) {
336
- files.push(...(await collectTemplateFiles(sourcePath, destinationPath, destinationRelative)));
337
- continue;
338
- }
339
-
340
- if (!entry.isFile()) {
341
- continue;
342
- }
343
-
344
- files.push({ sourcePath, destinationPath, destinationRelative });
345
- }
346
-
347
- return files;
348
- }
349
-
350
- function isPlainObject(value: unknown): value is Record<string, unknown> {
351
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
352
- }
353
-
354
- function uniqueStrings(values: string[]): string[] {
355
- return [...new Set(values)];
356
- }
package/src/validate.ts DELETED
@@ -1,141 +0,0 @@
1
- import { constants as fsConstants } from "node:fs";
2
- import { access } from "node:fs/promises";
3
- import path from "node:path";
4
-
5
- export type ValidateOptions = {
6
- targetDir: string;
7
- packageLayout?: boolean;
8
- };
9
-
10
- export type ValidateResult = {
11
- targetDir: string;
12
- ok: boolean;
13
- missing: string[];
14
- };
15
-
16
- const docs = [
17
- "index.md",
18
- "decision-basis.md",
19
- "cost-model.md",
20
- "glossary.md",
21
- "model.md",
22
- "operating-guide.md",
23
- "roles.md",
24
- "taxonomy.md",
25
- "workflows.md",
26
- "diagrams.md",
27
- "codex-integration.md",
28
- "open-questions.md"
29
- ];
30
-
31
- const processFiles = [
32
- "README.md",
33
- "decision-basis.yml",
34
- "cost-model.yml",
35
- "roles.yml",
36
- "taxonomy.yml",
37
- "workflows.yml",
38
- "controls.yml"
39
- ];
40
-
41
- const diagrams = [
42
- "00-decision-basis.mmd",
43
- "00-overview.mmd",
44
- "01-intake-triage.mmd",
45
- "02-product-definition.mmd",
46
- "03-engineering-execution.mmd",
47
- "04-qa-verification.mmd",
48
- "05-product-validation.mmd",
49
- "06-change-release-control.mmd",
50
- "07-deployment-operations.mmd",
51
- "08-support-incident-management.mmd",
52
- "09-problem-improvement.mmd",
53
- "10-risk-control-management.mmd",
54
- "11-audit-evidence-capture.mmd"
55
- ];
56
-
57
- export async function validateScaffold(options: ValidateOptions): Promise<ValidateResult> {
58
- const targetDir = path.resolve(options.targetDir);
59
- const requiredFiles = options.packageLayout
60
- ? packageRequiredFiles()
61
- : installedRequiredFiles();
62
-
63
- const missing: string[] = [];
64
-
65
- for (const requiredFile of requiredFiles) {
66
- if (!(await fileExists(path.join(targetDir, requiredFile)))) {
67
- missing.push(requiredFile);
68
- }
69
- }
70
-
71
- return {
72
- targetDir,
73
- ok: missing.length === 0,
74
- missing
75
- };
76
- }
77
-
78
- function packageRequiredFiles(): string[] {
79
- return [
80
- ...docs.map((file) => path.join("docs", file)),
81
- ...processFiles.map((file) => path.join("templates", "process", file)),
82
- ...diagrams.map((file) => path.join("templates", "process", "diagrams", file)),
83
- ".env.example",
84
- path.join("api", "mcp.js"),
85
- path.join("api", "dxcomplete.js"),
86
- path.join("api", "dxcomplete-service.js"),
87
- path.join("api", "auth", "callback", "google.js"),
88
- path.join("dxcomplete", "workspace.json"),
89
- path.join("templates", "AGENTS.md"),
90
- path.join("scripts", "check-env-surface.mjs"),
91
- path.join("scripts", "smoke-mcp-http.mjs"),
92
- path.join("scripts", "runtime-work-order.mjs"),
93
- path.join("scripts", "check-public-copy.mjs"),
94
- path.join("scripts", "check-service-boundary.mjs"),
95
- path.join("templates", "next", "pages", "api", "mcp.js"),
96
- path.join("templates", "next", "pages", "api", "dxcomplete.js"),
97
- path.join("templates", "next", "pages", "api", "dxcomplete", "[...path].js"),
98
- path.join("templates", "next", "pages", "api", "auth", "callback", "google.js"),
99
- path.join("templates", "next", "vercel.json"),
100
- path.join("templates", "github", "workflows", "dxcomplete.yml"),
101
- path.join("src", "cli.ts"),
102
- path.join("src", "install-manifest.ts"),
103
- path.join("src", "init.ts"),
104
- path.join("src", "package-root.ts"),
105
- path.join("src", "http", "server.ts"),
106
- path.join("src", "http", "service.ts"),
107
- path.join("src", "mcp", "server.ts"),
108
- path.join("src", "runtime", "auth.ts"),
109
- path.join("src", "runtime", "check.ts"),
110
- path.join("src", "runtime", "config.ts"),
111
- path.join("src", "runtime", "mongo.ts"),
112
- path.join("src", "runtime", "records.ts"),
113
- path.join("src", "runtime", "workspace.ts"),
114
- path.join("src", "upgrade.ts"),
115
- path.join("src", "version.ts"),
116
- path.join("src", "validate.ts")
117
- ];
118
- }
119
-
120
- function installedRequiredFiles(): string[] {
121
- return [
122
- path.join("pages", "api", "mcp.js"),
123
- path.join("pages", "api", "dxcomplete.js"),
124
- path.join("pages", "api", "dxcomplete", "[...path].js"),
125
- path.join("pages", "api", "auth", "callback", "google.js"),
126
- "vercel.json",
127
- path.join("dxcomplete", "workspace.json"),
128
- ...docs.map((file) => path.join("dxcomplete", "docs", file)),
129
- ...processFiles.map((file) => path.join("dxcomplete", "process", file)),
130
- ...diagrams.map((file) => path.join("dxcomplete", "process", "diagrams", file))
131
- ];
132
- }
133
-
134
- async function fileExists(filePath: string): Promise<boolean> {
135
- try {
136
- await access(filePath, fsConstants.F_OK);
137
- return true;
138
- } catch {
139
- return false;
140
- }
141
- }
package/src/version.ts DELETED
@@ -1,16 +0,0 @@
1
- import { createRequire } from "node:module";
2
-
3
- const require = createRequire(import.meta.url);
4
- const packageJson = require("../package.json") as { version?: unknown };
5
-
6
- export const DXCOMPLETE_PACKAGE_VERSION = readPackageVersion(packageJson.version);
7
- export const WORKSPACE_COMPATIBILITY_VERSION = 1;
8
- export const MCP_SURFACE_ID = "dxc-mcp-surface";
9
-
10
- function readPackageVersion(value: unknown): string {
11
- if (typeof value !== "string" || !value.trim()) {
12
- throw new Error("DX Complete package.json version must be a non-empty string.");
13
- }
14
-
15
- return value;
16
- }