@orkestrel/scaffold 0.0.15 → 0.0.17

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.
@@ -1177,7 +1177,7 @@ export declare function coreViteConfig(): string;
1177
1177
  readonly content: string;
1178
1178
  readonly freshness: Freshness;
1179
1179
  readonly note?: string;
1180
- /** SHA-256 of the observed local mirror, or `absent`; omitted outside target-aware pulls. */
1180
+ /** SHA-256 of the observed local mirror, or `absent`; omitted outside target-aware synchronization. */
1181
1181
  readonly baseline?: string;
1182
1182
  }
1183
1183
 
@@ -2275,7 +2275,7 @@ export declare function coreViteConfig(): string;
2275
2275
  export declare function rootViteConfig(src: readonly Environment[], facts?: ViteFacts): string;
2276
2276
 
2277
2277
  /** The devDependency range generated packages pin `@orkestrel/scaffold` at. */
2278
- export declare const SCAFFOLD_RANGE = "^0.0.15";
2278
+ export declare const SCAFFOLD_RANGE = "^0.0.17";
2279
2279
 
2280
2280
  /**
2281
2281
  * Carries a `ScaffoldErrorCode` + optional `context` (AGENTS §12).
@@ -2537,7 +2537,7 @@ export declare function coreViteConfig(): string;
2537
2537
  export declare const SYNC_BASELINE_PATTERN: RegExp;
2538
2538
 
2539
2539
  /**
2540
- * The whole outcome of a `Sync.pull`.
2540
+ * The whole outcome of a `Sync.pull` or `Sync.mirror` synchronization.
2541
2541
  *
2542
2542
  * @remarks
2543
2543
  * `clean` is `true` iff no drift AND no failures; `failed` is the count of
@@ -1177,7 +1177,7 @@ export declare function coreViteConfig(): string;
1177
1177
  readonly content: string;
1178
1178
  readonly freshness: Freshness;
1179
1179
  readonly note?: string;
1180
- /** SHA-256 of the observed local mirror, or `absent`; omitted outside target-aware pulls. */
1180
+ /** SHA-256 of the observed local mirror, or `absent`; omitted outside target-aware synchronization. */
1181
1181
  readonly baseline?: string;
1182
1182
  }
1183
1183
 
@@ -2275,7 +2275,7 @@ export declare function coreViteConfig(): string;
2275
2275
  export declare function rootViteConfig(src: readonly Environment[], facts?: ViteFacts): string;
2276
2276
 
2277
2277
  /** The devDependency range generated packages pin `@orkestrel/scaffold` at. */
2278
- export declare const SCAFFOLD_RANGE = "^0.0.15";
2278
+ export declare const SCAFFOLD_RANGE = "^0.0.17";
2279
2279
 
2280
2280
  /**
2281
2281
  * Carries a `ScaffoldErrorCode` + optional `context` (AGENTS §12).
@@ -2537,7 +2537,7 @@ export declare function coreViteConfig(): string;
2537
2537
  export declare const SYNC_BASELINE_PATTERN: RegExp;
2538
2538
 
2539
2539
  /**
2540
- * The whole outcome of a `Sync.pull`.
2540
+ * The whole outcome of a `Sync.pull` or `Sync.mirror` synchronization.
2541
2541
  *
2542
2542
  * @remarks
2543
2543
  * `clean` is `true` iff no drift AND no failures; `failed` is the count of
@@ -226,7 +226,7 @@ var DEFAULT_VERSION = "0.0.1";
226
226
  /** The `engines.node` range the `blueprint` builder fills. */
227
227
  var DEFAULT_ENGINES = `>=${MINIMUM_NODE_VERSION}`;
228
228
  /** The devDependency range generated packages pin `@orkestrel/scaffold` at. */
229
- var SCAFFOLD_RANGE = "^0.0.15";
229
+ var SCAFFOLD_RANGE = "^0.0.17";
230
230
  /** Tooling versions shared by scaffold and every generated workspace. */
231
231
  var BASE_DEV_DEPENDENCIES = Object.freeze({
232
232
  "@microsoft/api-extractor": "^7.58.12",
@@ -4139,9 +4139,7 @@ ${EXPORT_KEYWORD} ${FUNCTION_KEYWORD} isBrowserVuePath(path: string): boolean {
4139
4139
  content: `import { globSync{{browserPolicySpecifier}} } from 'node:fs'
4140
4140
  import { describe, expect, it } from 'vitest'
4141
4141
  import { isBrowserVuePath } from './setup.js'
4142
- import { inspectCodingWorkspace } from './setupPolicy.js'
4143
- {{browserPolicyImport}}
4144
- {{vuePolicyImport}}
4142
+ import { inspectCodingWorkspace } from './setupPolicy.js'{{browserPolicyImport}}{{vuePolicyImport}}
4145
4143
 
4146
4144
  describe('repository coding law', () => {
4147
4145
  it('keeps Vue single-file components exclusively in browser environments', () => {
@@ -4152,8 +4150,7 @@ describe('repository coding law', () => {
4152
4150
 
4153
4151
  it('enforces source placement, exports, readonly contracts, and syntax law', () => {
4154
4152
  {{workspacePolicyAssertion}}
4155
- })
4156
- {{browserPolicyTest}}
4153
+ }){{browserPolicyTest}}
4157
4154
  })
4158
4155
  `
4159
4156
  }),
@@ -5875,7 +5872,7 @@ ${renderedProjects}
5875
5872
  ${fitsPrintWidth(inlineRegistrations) ? inlineRegistrations : ` [
5876
5873
  ${renderedRegistrations.map((registration) => ` ${registration},`).join("\n")}
5877
5874
  ],`}
5878
- chromiumPath !== undefined,
5875
+ browserOptions !== undefined,
5879
5876
  process.argv,
5880
5877
  ),`;
5881
5878
  }
@@ -5899,6 +5896,8 @@ ${renderedRegistrations.map((registration) => ` ${registration},`).join("\n")}
5899
5896
  */
5900
5897
  function viteHeader(machinery) {
5901
5898
  const { browser: needsBrowser, vue: needsVue, output: needsOutput } = machinery;
5899
+ const playwrightTypeImports = needsBrowser ? `import type { PlaywrightProviderOptions } from '@vitest/browser-playwright'
5900
+ ` : "";
5902
5901
  const playwrightImports = needsBrowser ? `import { playwright } from '@vitest/browser-playwright'
5903
5902
  import { chromium } from 'playwright'
5904
5903
  ` : "";
@@ -6209,7 +6208,9 @@ import { parse as parseVue } from 'vue/compiler-sfc'
6209
6208
  ? undefined
6210
6209
  : packageRootOf(packageName, physicalSource)
6211
6210
  if (packageRoot === undefined || !containedPath(packageRoot, physicalSource)) {
6212
- this.error('Resolved dependencies must remain inside their physical package root')
6211
+ return this.error(
6212
+ 'Resolved dependencies must remain inside their physical package root',
6213
+ )
6213
6214
  }
6214
6215
  trustedPackageRoots.add(packageRoot)
6215
6216
  }
@@ -6217,7 +6218,7 @@ import { parse as parseVue } from 'vue/compiler-sfc'
6217
6218
  }
6218
6219
  const resolvedSource = workspacePath(physicalSource)
6219
6220
  if (resolvedSource === undefined) {
6220
- this.error('Environment modules cannot import files outside the workspace')
6221
+ return this.error('Environment modules cannot import files outside the workspace')
6221
6222
  }
6222
6223
  const assetError = environmentPathError(owner, resolvedSource)
6223
6224
  if (assetError !== undefined) this.error(assetError)
@@ -7246,7 +7247,7 @@ ${needsVue ? ` configureServer(server) {
7246
7247
  }
7247
7248
  }
7248
7249
  `;
7249
- return `${viteTypeImports}
7250
+ return `${playwrightTypeImports}${viteTypeImports}
7250
7251
  ${needsBrowser ? `import { isCSSRequest, parseSync, preprocessCSS, transformWithOxc, Visitor } from 'vite'
7251
7252
  ` : `import { parseSync, transformWithOxc, Visitor } from 'vite'
7252
7253
  `}import { defineConfig, mergeConfig } from 'vitest/config'
@@ -7254,7 +7255,7 @@ import tsconfig from './tsconfig.json' with { type: 'json' }
7254
7255
  import { fileURLToPath, URL } from 'node:url'
7255
7256
  import { isBuiltin } from 'node:module'
7256
7257
  import {
7257
- closeSync,
7258
+ ${needsBrowser ? " accessSync,\n" : ""} closeSync,
7258
7259
  constants as FS_CONSTANTS,
7259
7260
  existsSync,
7260
7261
  fstatSync,
@@ -7263,7 +7264,15 @@ import {
7263
7264
  ${needsBrowser ? " readdirSync,\n" : ""} readSync,
7264
7265
  realpathSync,
7265
7266
  ${needsBrowser ? " statSync,\n" : ""}} from 'node:fs'
7266
- import { ${needsBrowser ? "basename, " : ""}dirname, isAbsolute, relative, resolve as resolvePath, sep } from 'node:path'
7267
+ ${needsBrowser ? `import {
7268
+ basename,
7269
+ join,
7270
+ dirname,
7271
+ isAbsolute,
7272
+ relative,
7273
+ resolve as resolvePath,
7274
+ sep,
7275
+ } from 'node:path'` : `import { dirname, isAbsolute, relative, resolve as resolvePath, sep } from 'node:path'`}
7267
7276
  ${playwrightImports}${vueImports}${needsBrowser ? `\n/** Chromium executable layouts inside a \`chromium-<revision>\` browsers-directory entry, per platform. */
7268
7277
  ${EXPORT_KEYWORD} ${CONST_KEYWORD} CHROMIUM_LAYOUTS = Object.freeze([
7269
7278
  'chrome-linux/chrome',
@@ -7274,15 +7283,64 @@ ${EXPORT_KEYWORD} ${CONST_KEYWORD} CHROMIUM_LAYOUTS = Object.freeze([
7274
7283
  'chrome-mac-arm64/Chromium.app/Contents/MacOS/Chromium',
7275
7284
  ])
7276
7285
 
7286
+ /** Stable Playwright Chromium channels and their standard executable layouts. */
7287
+ ${EXPORT_KEYWORD} ${CONST_KEYWORD} SYSTEM_BROWSER_CHANNELS = Object.freeze([
7288
+ Object.freeze({
7289
+ channel: 'chrome',
7290
+ layouts: Object.freeze({
7291
+ linux: '/opt/google/chrome/chrome',
7292
+ darwin: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
7293
+ win32: Object.freeze(['Google', 'Chrome', 'Application', 'chrome.exe']),
7294
+ }),
7295
+ }),
7296
+ Object.freeze({
7297
+ channel: 'msedge',
7298
+ layouts: Object.freeze({
7299
+ linux: '/opt/microsoft/msedge/msedge',
7300
+ darwin: '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge',
7301
+ win32: Object.freeze(['Microsoft', 'Edge', 'Application', 'msedge.exe']),
7302
+ }),
7303
+ }),
7304
+ ])
7305
+
7306
+ /**
7307
+ * Determine whether a path identifies an executable regular file.
7308
+ *
7309
+ * @param path - The filesystem path to inspect.
7310
+ * @returns Whether the path is a regular file with execute access.
7311
+ *
7312
+ * @example
7313
+ * \`\`\`ts
7314
+ * isBrowserExecutable('/opt/google/chrome/chrome')
7315
+ * \`\`\`
7316
+ */
7317
+ ${EXPORT_KEYWORD} function isBrowserExecutable(path: string): boolean {
7318
+ try {
7319
+ if (!statSync(path).isFile()) return false
7320
+ accessSync(path, FS_CONSTANTS.X_OK)
7321
+ return true
7322
+ } catch {
7323
+ return false
7324
+ }
7325
+ }
7326
+
7277
7327
  /**
7278
- * Resolve a launchable Chromium executable: the pinned revision when installed,
7328
+ * Resolve a launchable Playwright-managed Chromium executable: the pinned revision when installed,
7279
7329
  * otherwise a \`chromium\` / \`chromium.exe\` alias or any other \`chromium-*\`
7280
7330
  * revision under the same Playwright browsers directory. A pinned-revision miss
7281
7331
  * is not Chromium absence — managed containers ship one usable build (often
7282
7332
  * behind a revision-agnostic alias) for many Playwright versions.
7333
+ *
7334
+ * @param pinned - The executable path for Playwright's pinned Chromium revision.
7335
+ * @returns The managed executable path, or \`undefined\` when none is executable.
7336
+ *
7337
+ * @example
7338
+ * \`\`\`ts
7339
+ * resolveManagedBrowser(chromium.executablePath())
7340
+ * \`\`\`
7283
7341
  */
7284
- ${EXPORT_KEYWORD} function resolveChromium(pinned: string): string | undefined {
7285
- if (existsSync(pinned)) return pinned
7342
+ ${EXPORT_KEYWORD} function resolveManagedBrowser(pinned: string): string | undefined {
7343
+ if (isBrowserExecutable(pinned)) return pinned
7286
7344
  let revisionRoot = dirname(pinned)
7287
7345
  for (;;) {
7288
7346
  if (/^chromium-\\d+$/.test(basename(revisionRoot))) break
@@ -7293,7 +7351,7 @@ ${EXPORT_KEYWORD} function resolveChromium(pinned: string): string | undefined {
7293
7351
  const browsersRoot = dirname(revisionRoot)
7294
7352
  for (const alias of ['chromium', 'chromium.exe']) {
7295
7353
  const candidate = resolvePath(browsersRoot, alias)
7296
- if (existsSync(candidate) && statSync(candidate).isFile()) return candidate
7354
+ if (isBrowserExecutable(candidate)) return candidate
7297
7355
  }
7298
7356
  let entries: readonly string[]
7299
7357
  try {
@@ -7307,18 +7365,89 @@ ${EXPORT_KEYWORD} function resolveChromium(pinned: string): string | undefined {
7307
7365
  for (const revision of revisions) {
7308
7366
  for (const layout of CHROMIUM_LAYOUTS) {
7309
7367
  const candidate = resolvePath(browsersRoot, revision, layout)
7310
- if (existsSync(candidate)) return candidate
7368
+ if (isBrowserExecutable(candidate)) return candidate
7311
7369
  }
7312
7370
  }
7313
7371
  return undefined
7314
7372
  }
7315
7373
 
7316
- ${CONST_KEYWORD} chromiumPinned = chromium.executablePath()
7317
- ${CONST_KEYWORD} chromiumPath = resolveChromium(chromiumPinned)
7318
- ${CONST_KEYWORD} chromiumOptions =
7319
- chromiumPath === undefined || chromiumPath === chromiumPinned
7320
- ? {}
7321
- : { launchOptions: { executablePath: chromiumPath } }
7374
+ /**
7375
+ * Resolve the first installed stable system Chromium channel.
7376
+ *
7377
+ * @param platform - The Node platform whose standard layouts should be probed.
7378
+ * @param environment - The process environment supplying Windows installation roots.
7379
+ * @returns \`chrome\`, then \`msedge\`, or \`undefined\` when neither is executable.
7380
+ *
7381
+ * @example
7382
+ * \`\`\`ts
7383
+ * resolveSystemBrowser(process.platform, process.env)
7384
+ * \`\`\`
7385
+ */
7386
+ ${EXPORT_KEYWORD} function resolveSystemBrowser(
7387
+ platform: NodeJS.Platform,
7388
+ environment: NodeJS.ProcessEnv,
7389
+ ): string | undefined {
7390
+ if (platform !== 'linux' && platform !== 'darwin' && platform !== 'win32') return undefined
7391
+ const roots = new Set<string>()
7392
+ if (platform === 'win32') {
7393
+ for (const root of [
7394
+ environment.LOCALAPPDATA,
7395
+ environment.PROGRAMFILES,
7396
+ environment['PROGRAMFILES(X86)'],
7397
+ ]) {
7398
+ if (root !== undefined && root.length > 0) roots.add(root)
7399
+ }
7400
+ const homeDrive = environment.HOMEDRIVE
7401
+ if (homeDrive !== undefined && homeDrive.length > 0) {
7402
+ roots.add(join(homeDrive, 'Program Files'))
7403
+ roots.add(join(homeDrive, 'Program Files (x86)'))
7404
+ }
7405
+ }
7406
+ for (const browser of SYSTEM_BROWSER_CHANNELS) {
7407
+ if (platform === 'win32') {
7408
+ for (const root of roots) {
7409
+ if (isBrowserExecutable(join(root, ...browser.layouts.win32))) return browser.channel
7410
+ }
7411
+ continue
7412
+ }
7413
+ if (isBrowserExecutable(browser.layouts[platform])) return browser.channel
7414
+ }
7415
+ return undefined
7416
+ }
7417
+
7418
+ /**
7419
+ * Resolve launch options for a managed Chromium or stable system browser.
7420
+ *
7421
+ * @param pinned - The executable path for Playwright's pinned Chromium revision.
7422
+ * @param platform - The Node platform whose standard system layouts should be probed.
7423
+ * @param environment - The process environment supplying Windows installation roots.
7424
+ * @returns Provider options for managed Chromium, Chrome, or Edge, or \`undefined\`.
7425
+ *
7426
+ * @remarks
7427
+ * An installed pinned revision returns an empty object so Playwright retains
7428
+ * its default launch semantics. A different managed executable is selected by
7429
+ * path; a system browser is selected by its stable Playwright channel.
7430
+ *
7431
+ * @example
7432
+ * \`\`\`ts
7433
+ * resolveBrowser(chromium.executablePath(), process.platform, process.env)
7434
+ * \`\`\`
7435
+ */
7436
+ ${EXPORT_KEYWORD} function resolveBrowser(
7437
+ pinned: string,
7438
+ platform: NodeJS.Platform,
7439
+ environment: NodeJS.ProcessEnv,
7440
+ ): PlaywrightProviderOptions | undefined {
7441
+ const managed = resolveManagedBrowser(pinned)
7442
+ if (managed !== undefined) {
7443
+ return managed === pinned ? {} : { launchOptions: { executablePath: managed } }
7444
+ }
7445
+ const channel = resolveSystemBrowser(platform, environment)
7446
+ return channel === undefined ? undefined : { launchOptions: { channel } }
7447
+ }
7448
+
7449
+ ${CONST_KEYWORD} browserPinned = chromium.executablePath()
7450
+ ${CONST_KEYWORD} browserOptions = resolveBrowser(browserPinned, process.platform, process.env)
7322
7451
  ` : ""}
7323
7452
  ${EXPORT_KEYWORD} function resolveWorkspacePath(relativePath: string): string {
7324
7453
  return fileURLToPath(new URL(relativePath, import.meta.url))
@@ -7367,7 +7496,9 @@ ${needsBrowser ? `${EXPORT_KEYWORD} function gateBrowserProjects(
7367
7496
  projects.push(registration.project())
7368
7497
  }
7369
7498
  if (gated.length === 0) return { projects }
7370
- console.warn(\`browser projects skipped: Chromium absent (\${gated.join(', ')})\`)
7499
+ console.warn(
7500
+ \`browser projects skipped: no Playwright Chromium, Chrome, or Edge found (\${gated.join(', ')})\`,
7501
+ )
7371
7502
  const filters: string[] = []
7372
7503
  let readable = true
7373
7504
  for (let index = 0; index < argv.length; index += 1) {
@@ -7658,7 +7789,7 @@ ${EXPORT_KEYWORD} const srcBrowser = (config?: UserConfig): UserConfig =>
7658
7789
  }),
7659
7790
  browser: {
7660
7791
  enabled: true,
7661
- provider: playwright(chromiumOptions),
7792
+ provider: playwright(browserOptions),
7662
7793
  instances: [{ browser: 'chromium', headless: true }],
7663
7794
  },
7664
7795
  fileParallelism: false,
@@ -7790,7 +7921,7 @@ ${EXPORT_KEYWORD} const srcBrowser = (config?: UserConfig): UserConfig =>
7790
7921
  }),
7791
7922
  browser: {
7792
7923
  enabled: true,
7793
- provider: playwright(chromiumOptions),
7924
+ provider: playwright(browserOptions),
7794
7925
  instances: [{ browser: 'chromium', headless: true }],
7795
7926
  },
7796
7927
  fileParallelism: false,
@@ -7955,7 +8086,7 @@ ${EXPORT_KEYWORD} const srcBrowser = (config?: UserConfig): UserConfig =>
7955
8086
  }),
7956
8087
  browser: {
7957
8088
  enabled: true,
7958
- provider: playwright(chromiumOptions),
8089
+ provider: playwright(browserOptions),
7959
8090
  instances: [{ browser: 'chromium', headless: true }],
7960
8091
  },
7961
8092
  fileParallelism: false,
@@ -8084,7 +8215,7 @@ ${EXPORT_KEYWORD} function appBrowser(...config: readonly never[]): UserConfig {
8084
8215
  },
8085
8216
  browser: {
8086
8217
  enabled: true,
8087
- provider: playwright(chromiumOptions),
8218
+ provider: playwright(browserOptions),
8088
8219
  instances: [{ browser: 'chromium', headless: true }],
8089
8220
  },
8090
8221
  fileParallelism: false,
@@ -8651,9 +8782,8 @@ function paritySpecifiers(spec) {
8651
8782
  function testArtifacts(spec, pascal) {
8652
8783
  const hasBrowser = spec.src.includes("browser") || spec.app.includes("browser");
8653
8784
  const hasVue = spec.app.includes("browser");
8654
- const browserPolicySpecifier = hasBrowser ? ", accessSync, constants as FS_CONSTANTS, statSync" : "";
8655
- const browserPolicyImport = hasBrowser ? "import { chromium } from 'playwright'\nimport { resolveChromium } from '../vite.config.js'" : "";
8656
- const vuePolicyImport = hasVue ? "import { parse as parseVue } from 'vue/compiler-sfc'" : "";
8785
+ const browserPolicyImport = hasBrowser ? "\nimport { chromium } from 'playwright'\nimport { isBrowserExecutable, resolveBrowser, SYSTEM_BROWSER_CHANNELS } from '../vite.config.js'" : "";
8786
+ const vuePolicyImport = hasVue ? "\nimport { parse as parseVue } from 'vue/compiler-sfc'" : "";
8657
8787
  const workspacePolicyAssertion = hasVue ? `expect(
8658
8788
  inspectCodingWorkspace(process.cwd(), (path, content) => {
8659
8789
  const parsed = parseVue(content, { filename: path })
@@ -8664,15 +8794,21 @@ function testArtifacts(spec, pascal) {
8664
8794
  }),
8665
8795
  ).toEqual([])` : "expect(inspectCodingWorkspace(process.cwd())).toEqual([])";
8666
8796
  const browserPolicyTest = hasBrowser ? `
8667
- it('resolves Chromium only to a real executable file', () => {
8668
- const chromiumPath = resolveChromium(chromium.executablePath())
8669
- if (chromiumPath === undefined) return
8670
8797
 
8671
- expect(statSync(chromiumPath).isFile()).toBe(true)
8672
- expect(() => accessSync(chromiumPath, FS_CONSTANTS.X_OK)).not.toThrow()
8798
+ it('resolves only a real managed executable or stable system browser channel', () => {
8799
+ const options = resolveBrowser(chromium.executablePath(), process.platform, process.env)
8800
+ let valid = options === undefined
8801
+ if (options !== undefined) {
8802
+ const channel = options.launchOptions?.channel
8803
+ valid =
8804
+ channel === undefined
8805
+ ? isBrowserExecutable(options.launchOptions?.executablePath ?? chromium.executablePath())
8806
+ : SYSTEM_BROWSER_CHANNELS.some((browser) => browser.channel === channel)
8807
+ }
8808
+ expect(valid).toBe(true)
8673
8809
  })` : "";
8674
8810
  const artifacts = [fillArtifact("tests/setup.ts", "tests", "setup", {}), fillArtifact("tests/policy.test.ts", "tests", "policyTest", {
8675
- browserPolicySpecifier,
8811
+ browserPolicySpecifier: "",
8676
8812
  browserPolicyImport,
8677
8813
  browserPolicyTest,
8678
8814
  vuePolicyImport,