carrick 0.3.77 → 0.3.78

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "carrick",
3
- "version": "0.3.77",
3
+ "version": "0.3.78",
4
4
  "description": "The API contract index for a TypeScript workspace: what the other services do with the routes and calls in the file you are editing, in your editor and in your agent's context",
5
5
  "keywords": [
6
6
  "typescript",
@@ -57,11 +57,11 @@
57
57
  "zod": "^3.23.0"
58
58
  },
59
59
  "optionalDependencies": {
60
- "@carrick-tools/cli-darwin-arm64": "0.3.77",
61
- "@carrick-tools/cli-darwin-x64": "0.3.77",
62
- "@carrick-tools/cli-linux-arm64": "0.3.77",
63
- "@carrick-tools/cli-linux-x64": "0.3.77",
64
- "@carrick-tools/cli-win32-x64": "0.3.77"
60
+ "@carrick-tools/cli-darwin-arm64": "0.3.78",
61
+ "@carrick-tools/cli-darwin-x64": "0.3.78",
62
+ "@carrick-tools/cli-linux-arm64": "0.3.78",
63
+ "@carrick-tools/cli-linux-x64": "0.3.78",
64
+ "@carrick-tools/cli-win32-x64": "0.3.78"
65
65
  },
66
66
  "devDependencies": {
67
67
  "@types/node": "^24.13.3",
@@ -32,6 +32,25 @@ export type { CaptureStubOptions, CaptureStubResult } from './api.js';
32
32
  export { DenoProject, findDenoConfig } from './deno-project.js';
33
33
  export { runCheck } from './check.js';
34
34
  export type { CheckProgress } from './check.js';
35
+ /**
36
+ * The name of THIS capture's surface entry, without an extension
37
+ * (carrick#1046).
38
+ *
39
+ * The entry has to live inside the effective `rootDir` — an entry beside a
40
+ * `rootDir` of `src` fails TS6059 — so it is written into the scanned tree and
41
+ * unlinked afterwards. One name per repo root made two captures of the same
42
+ * tree share a single file: whichever finished first unlinked it while the
43
+ * other's program was still reading it, and every alias whose print anchors in
44
+ * that destination then demoted to `structural_fallback` with an accessibility
45
+ * reason that described the harness rather than the code. Concurrent captures
46
+ * of one tree are ordinary — the test suite does it on every run, and two
47
+ * services of a monorepo can share a root — so the name, not the locking, is
48
+ * what has to give.
49
+ *
50
+ * A leftover from an interrupted capture is also identifiable as one process's
51
+ * (carrick#1069), rather than a fixed name the next scan reads as source.
52
+ */
53
+ export declare function surfaceEntryFileName(): string;
35
54
  /** Same normalization intent as bundle_file_stems on the Rust side. */
36
55
  export declare function sanitizeServiceName(name: string): string;
37
56
  export declare function captureStub(opts: CaptureStubOptions): CaptureStubResult;
@@ -44,6 +44,31 @@ export { DenoProject, findDenoConfig } from './deno-project.js';
44
44
  // reaches it only through this door (index.js).
45
45
  export { runCheck } from './check.js';
46
46
  const SURFACE_ENTRY_BASENAME = '__carrick_surface__';
47
+ /** Captures made by this process, so each one's entry file has a name of its
48
+ * own. Paired with the pid it is unique across processes too. */
49
+ let surfaceEntrySequence = 0;
50
+ /**
51
+ * The name of THIS capture's surface entry, without an extension
52
+ * (carrick#1046).
53
+ *
54
+ * The entry has to live inside the effective `rootDir` — an entry beside a
55
+ * `rootDir` of `src` fails TS6059 — so it is written into the scanned tree and
56
+ * unlinked afterwards. One name per repo root made two captures of the same
57
+ * tree share a single file: whichever finished first unlinked it while the
58
+ * other's program was still reading it, and every alias whose print anchors in
59
+ * that destination then demoted to `structural_fallback` with an accessibility
60
+ * reason that described the harness rather than the code. Concurrent captures
61
+ * of one tree are ordinary — the test suite does it on every run, and two
62
+ * services of a monorepo can share a root — so the name, not the locking, is
63
+ * what has to give.
64
+ *
65
+ * A leftover from an interrupted capture is also identifiable as one process's
66
+ * (carrick#1069), rather than a fixed name the next scan reads as source.
67
+ */
68
+ export function surfaceEntryFileName() {
69
+ surfaceEntrySequence += 1;
70
+ return `${SURFACE_ENTRY_BASENAME}.${process.pid}.${surfaceEntrySequence}`;
71
+ }
47
72
  /** Same normalization intent as bundle_file_stems on the Rust side. */
48
73
  export function sanitizeServiceName(name) {
49
74
  return name.toLowerCase().replace(/[^a-z0-9._-]+/g, '-').replace(/^-+|-+$/g, '');
@@ -153,9 +178,11 @@ export function captureStub(opts) {
153
178
  const entryDir = parsed.options.rootDir
154
179
  ? path.resolve(path.dirname(configPath), parsed.options.rootDir)
155
180
  : repoRoot;
181
+ const surfaceEntry = surfaceEntryFileName();
182
+ const surfaceDeclaration = `${surfaceEntry}.d.ts`;
156
183
  const entryPath = deno
157
- ? path.join(deno.cacheDir, `${SURFACE_ENTRY_BASENAME}.ts`)
158
- : path.join(entryDir, `${SURFACE_ENTRY_BASENAME}.ts`);
184
+ ? path.join(deno.cacheDir, `${surfaceEntry}.ts`)
185
+ : path.join(entryDir, `${surfaceEntry}.ts`);
159
186
  fs.mkdirSync(path.dirname(entryPath), { recursive: true });
160
187
  // ---- Phase A: analysis program over placeholder entry + anchor sources ----
161
188
  let resolved;
@@ -250,7 +277,7 @@ export function captureStub(opts) {
250
277
  if (emitPartial) {
251
278
  errors.push(`declaration emit was partial: kept ${emitted.size} emitted file(s); ` +
252
279
  'aliases referencing unemitted modules are demoted to structural_fallback');
253
- resolved = demoteDanglingAliases({ resolved, emitted, declarationSources, staging });
280
+ resolved = demoteDanglingAliases({ resolved, emitted, declarationSources, staging, surfaceDeclaration });
254
281
  }
255
282
  // ---- Relocate the emitted tree into the stub package ----
256
283
  const typesDir = path.join(stubDir, 'types');
@@ -260,7 +287,7 @@ export function captureStub(opts) {
260
287
  let surfaceAbsPath = '';
261
288
  for (const [fileName, text] of emitted) {
262
289
  let rel = path.relative(staging, fileName).split(path.sep).join('/');
263
- if (path.basename(rel) === `${SURFACE_ENTRY_BASENAME}.d.ts`) {
290
+ if (path.basename(rel) === surfaceDeclaration) {
264
291
  const source = sourceByEmitted.get(rel);
265
292
  sourceByEmitted.delete(rel);
266
293
  rel = 'surface.d.ts';
@@ -422,7 +449,7 @@ function demoteDanglingAliases(args) {
422
449
  let surfaceKey;
423
450
  for (const fileName of args.emitted.keys()) {
424
451
  const rel = path.relative(args.staging, fileName).split(path.sep).join('/');
425
- if (path.basename(rel) === `${SURFACE_ENTRY_BASENAME}.d.ts`)
452
+ if (path.basename(rel) === args.surfaceDeclaration)
426
453
  surfaceKey = fileName;
427
454
  if (rel.endsWith('.d.ts'))
428
455
  treeModules.add(rel.slice(0, -'.d.ts'.length));