adamantite 0.43.0 → 0.44.0
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/README.md +32 -9
- package/dist/index.js +34 -29
- package/dist/presets/lint/effect.js +5 -0
- package/dist/presets/lint/jest.js +6 -2
- package/dist/presets/lint/vitest.js +28 -6
- package/package.json +21 -19
- package/skills/adamantite/SKILL.md +3 -1
package/README.md
CHANGED
|
@@ -297,8 +297,8 @@ hoist, dependencies, build output, and generated code are only skipped when your
|
|
|
297
297
|
`.gitignore` happens to cover them:
|
|
298
298
|
|
|
299
299
|
```ts
|
|
300
|
-
import { defineConfig } from "oxlint"
|
|
301
300
|
import core from "adamantite/lint"
|
|
301
|
+
import { defineConfig } from "oxlint"
|
|
302
302
|
|
|
303
303
|
export default defineConfig({
|
|
304
304
|
extends: [core],
|
|
@@ -327,10 +327,10 @@ Globs match paths relative to the working directory. Set `allow` to use another
|
|
|
327
327
|
`hooks` to change the list of reported hooks:
|
|
328
328
|
|
|
329
329
|
```ts
|
|
330
|
-
import { defineConfig } from "oxlint"
|
|
331
330
|
import core from "adamantite/lint"
|
|
332
331
|
import react from "adamantite/lint/react"
|
|
333
332
|
import reactStrict from "adamantite/lint/react-strict"
|
|
333
|
+
import { defineConfig } from "oxlint"
|
|
334
334
|
|
|
335
335
|
export default defineConfig({
|
|
336
336
|
extends: [core, react, reactStrict],
|
|
@@ -418,7 +418,7 @@ after it. Adamantite runs it in these places:
|
|
|
418
418
|
- `adamantite prepare`, which the `prepare` script runs after a bare install, such as
|
|
419
419
|
`npm install`, `npm ci`, or a fresh clone in CI.
|
|
420
420
|
- `adamantite init` and `adamantite update`, after they install packages. A named install,
|
|
421
|
-
such as `npm install -D oxlint@1.
|
|
421
|
+
such as `npm install -D oxlint@1.88.0`, does not run the `prepare` script. If you change one
|
|
422
422
|
of those versions yourself, doctor reports the version drift, and `adamantite update`
|
|
423
423
|
installs the pinned version and patches it.
|
|
424
424
|
|
|
@@ -438,7 +438,9 @@ When you select the preset, `adamantite init` does these steps:
|
|
|
438
438
|
|
|
439
439
|
`adamantite doctor` reports each missing part, and `adamantite update` keeps
|
|
440
440
|
`@effect/tsgo` on its pinned version. Each `@effect/tsgo` release supports only some Oxlint,
|
|
441
|
-
oxlint-tsgolint, and TypeScript versions, so Adamantite moves the pins together.
|
|
441
|
+
oxlint-tsgolint, and TypeScript versions, so Adamantite moves the pins together. If you
|
|
442
|
+
install a TypeScript version that the pinned `@effect/tsgo` does not support, the `prepare`
|
|
443
|
+
script fails.
|
|
442
444
|
|
|
443
445
|
A production-only install, such as `npm ci --omit=dev` or `pnpm install --prod`, still runs
|
|
444
446
|
the `prepare` script, but it does not install Adamantite, so the install fails with
|
|
@@ -463,6 +465,12 @@ it in `allowedUnstableApis`:
|
|
|
463
465
|
}
|
|
464
466
|
```
|
|
465
467
|
|
|
468
|
+
Effect 4.0.2 and later tag each module as stable or unstable. Unstable modules can have
|
|
469
|
+
breaking changes in minor releases. The unstable modules include the platform modules, such
|
|
470
|
+
as `effect/FileSystem`, `effect/Path`, and `effect/Terminal`, and all modules in
|
|
471
|
+
`@effect/platform-node` and `@effect/vitest`. A project that uses them must list them. An
|
|
472
|
+
entry can be a module, such as `effect/Path`, or a full package, such as `@effect/vitest`.
|
|
473
|
+
|
|
466
474
|
The preset enables only rules that report Effect code. It does not ban platform APIs, such
|
|
467
475
|
as `Date.now()` or `process.env`, in code that is not Effect code. Inside Effect code, it
|
|
468
476
|
reports them, because `Clock`, `Random`, and `Config` let tests control them. See
|
|
@@ -483,9 +491,9 @@ reports them, because `Clock`, `Random`, and `Config` let tests control them. Se
|
|
|
483
491
|
Set `maxDepth` and `maxProperties` to change the destructuring limits:
|
|
484
492
|
|
|
485
493
|
```ts
|
|
486
|
-
import { defineConfig } from "oxlint"
|
|
487
494
|
import core from "adamantite/lint"
|
|
488
495
|
import strict from "adamantite/lint/strict"
|
|
496
|
+
import { defineConfig } from "oxlint"
|
|
489
497
|
|
|
490
498
|
export default defineConfig({
|
|
491
499
|
extends: [core, strict],
|
|
@@ -507,9 +515,9 @@ or `src/components/ui` and discovers the stylesheet that imports Tailwind. When
|
|
|
507
515
|
components live elsewhere, set `settings.shadcn.ui`:
|
|
508
516
|
|
|
509
517
|
```ts
|
|
510
|
-
import { defineConfig } from "oxlint"
|
|
511
518
|
import core from "adamantite/lint"
|
|
512
519
|
import shadcn from "adamantite/lint/shadcn"
|
|
520
|
+
import { defineConfig } from "oxlint"
|
|
513
521
|
|
|
514
522
|
export default defineConfig({
|
|
515
523
|
extends: [core, shadcn],
|
|
@@ -562,9 +570,9 @@ export default defineRule({
|
|
|
562
570
|
|
|
563
571
|
```ts
|
|
564
572
|
// oxlint.config.ts
|
|
565
|
-
import { defineConfig } from "oxlint"
|
|
566
573
|
import core from "adamantite/lint"
|
|
567
574
|
import custom from "adamantite/lint/custom"
|
|
575
|
+
import { defineConfig } from "oxlint"
|
|
568
576
|
|
|
569
577
|
export default defineConfig({
|
|
570
578
|
extends: [core, custom()],
|
|
@@ -599,8 +607,8 @@ root rules extends the root config:
|
|
|
599
607
|
|
|
600
608
|
```ts
|
|
601
609
|
// packages/web/oxlint.config.ts
|
|
602
|
-
import { defineConfig } from "oxlint"
|
|
603
610
|
import custom from "adamantite/lint/custom"
|
|
611
|
+
import { defineConfig } from "oxlint"
|
|
604
612
|
import root from "../../oxlint.config.ts"
|
|
605
613
|
|
|
606
614
|
export default defineConfig({ extends: [root, custom({ name: "web" })] })
|
|
@@ -647,10 +655,25 @@ npx skills add adelrodriguez/adamantite --list
|
|
|
647
655
|
npx skills add adelrodriguez/adamantite --skill adamantite
|
|
648
656
|
```
|
|
649
657
|
|
|
658
|
+
The Adamantite package also ships the skill. With pnpm 12.11 or later, `pnpm install` links
|
|
659
|
+
it into the agent skill directories that exist in the project, such as `.claude/skills`,
|
|
660
|
+
after you approve it. pnpm creates the directory only when the agent that runs pnpm sets an
|
|
661
|
+
environment variable that identifies it, such as `CLAUDECODE` for `.claude/skills`.
|
|
662
|
+
Otherwise, if no skill directory exists, the install fails, so create one before you
|
|
663
|
+
approve the skill:
|
|
664
|
+
|
|
665
|
+
```sh
|
|
666
|
+
mkdir -p .claude/skills
|
|
667
|
+
pnpm approve
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
The linked skill then matches the installed Adamantite version. To choose the directories,
|
|
671
|
+
set `skills.dirs`.
|
|
672
|
+
|
|
650
673
|
## Contributing
|
|
651
674
|
|
|
652
675
|
See [CONTRIBUTING.md](CONTRIBUTING.md) for the repository workflow. Contributors should
|
|
653
|
-
also read the [domain glossary](
|
|
676
|
+
also read the [domain glossary](GLOSSARY.md) and [architecture reference](docs/architecture.md).
|
|
654
677
|
|
|
655
678
|
## License
|
|
656
679
|
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
|
-
import*as e from"@effect/platform-node/NodeRuntime";import*as t from"effect/Effect";import*as n from"effect/Exit";import*as r from"effect/process/ChildProcessSpawner";import*as i from"effect/Runtime";import*as a from"effect/Stdio";import*as o from"@effect/platform-node/NodeServices";import*as s from"effect/Array";import*as c from"effect/cli/Command";import*as l from"effect/Layer";import*as u from"effect/cli/Flag";import*as d from"effect/Option";import f from"node:process";import{stripVTControlCharacters as p,styleText as m}from"node:util";import*as h from"effect/Console";import*as g from"effect/Context";import*as
|
|
2
|
-
`)}`}function
|
|
3
|
-
`)}var
|
|
4
|
-
`)}},
|
|
5
|
-
`)}},Te=class extends v.TaggedError(`FailedToReadFile`){get message(){return`Failed to read ${this.path?`\`${this.path}\``:`the target file`}.${O(this.cause)}`}},Ee=class extends v.TaggedError(`FailedToWriteFile`){get message(){return`Failed to write ${this.path?`\`${this.path}\``:`the target file`}.${O(this.cause)}`}},De=class extends v.TaggedError(`InvalidConfigFormat`){get message(){return`Invalid config format in ${this.path?`\`${this.path}\``:`the target config file`}. The config must be a JSON object (for example: {}).`}},Oe=class extends v.TaggedError(`InvalidAnalyzeOptions`){get message(){return`Invalid analyze options. ${this.reason}`}},ke=class extends v.TaggedError(`InvalidFixOptions`){get message(){return`Invalid fix options. ${this.reason}`}},k=class extends v.TaggedError(`InvalidInitOptions`){get message(){return`Invalid init options. ${this.reason}`}},Ae=class extends v.TaggedError(`InvalidRuleName`){get message(){return`Invalid rule name \`${this.name}\`. Use kebab-case that starts with a letter, such as \`no-process-env\`.`}},je=class extends v.TaggedError(`NoPackageManager`){get message(){return`No package manager detected. Please run this command from a project with a lockfile.${O(this.cause)}`}};v.TaggedError(`MissingPackageVersion`);var Me=class extends v.TaggedError(`OperationCancelled`){get message(){return`Operation cancelled.${this.reason?` Reason: ${this.reason}`:``}`}},Ne=class extends v.TaggedError(`PassthroughNotSupported`){get message(){return`Command \`adamantite ${this.command}\` does not invoke a single underlying CLI and cannot accept passthrough arguments.`}},Pe=class extends v.TaggedError(`VscodeCliNotFound`){get message(){return`VS Code CLI (\`code\`) not found. Please install it to manage extensions.${O(this.cause)}`}};const Fe=(e,t)=>h.log(`${m(`bold`,e)} ${m(`dim`,`· adamantite (${t})`)}`),Ie=()=>[f.env.NODE_OPTIONS,`--disable-warning=MODULE_TYPELESS_PACKAGE_JSON`].filter(Boolean).join(` `),Le=t.fn(`CommandRunner.exitCode`)(function*({args:e,command:n,cwd:r,detached:i,env:a,stderr:o=`inherit`,stdin:s=`ignore`,stdout:c=`inherit`}){return yield*t.scoped(t.gen(function*(){return yield*(yield*ee.make(n,e,{cwd:r,detached:i,env:{...a,NODE_OPTIONS:Ie()},extendEnv:!0,stderr:o,stdin:s,stdout:c})).exitCode})).pipe(t.mapError(e=>e.reason._tag===`NotFound`?new ge({command:n}):e))});var A=class e extends g.Service()(`CommandRunner`){static make(e){let n=t.fn(`CommandRunner.run`)(function*(t){t.title!==void 0&&(yield*Fe(t.title,t.command));let n=yield*e(t);if(n!==r.ExitCode(0))return yield*new _e({command:t.command,exitCode:n})}),i=e=>e.map((e,r)=>r===0?n(e):t.andThen(h.log(``),n(e)));return{exitCode:e,run:n,runAll:t.fn(`CommandRunner.runAll`)(function*(e){let n=yield*t.all(i(e),{concurrency:1,mode:`result`});yield*t.fromResult(_.all(n))}),runUntilFailure:t.fn(`CommandRunner.runUntilFailure`)(function*(e){yield*t.all(i(e),{concurrency:1,discard:!0})})}}static layer=l.effect(this)(t.gen(function*(){let n=yield*r.ChildProcessSpawner;return e.make(e=>Le(e).pipe(t.provideService(r.ChildProcessSpawner,n)))}))};const Re=g.Reference(`adamantite/ForwardedArguments`,{defaultValue:()=>[]});function j(e){return e}const ze=e=>S.FileSystem.pipe(t.flatMap(t=>t.makeDirectory(e,{recursive:!0})),t.mapError(t=>new ye({cause:t,path:e}))),M=e=>S.FileSystem.pipe(t.flatMap(t=>t.readFileString(e)),t.mapError(t=>new Te({cause:t,path:e}))),N=e=>S.FileSystem.pipe(t.flatMap(t=>t.readFileString(e)),t.map(e=>y(e,d.some)),t.catch(n=>n.reason._tag===`NotFound`?t.succeedNone:t.fail(new Te({cause:n,path:e})))),Be=e=>S.FileSystem.pipe(t.flatMap(t=>t.readDirectory(e)),t.map(e=>y(e,d.some)),t.catch(n=>n.reason._tag===`NotFound`||n.reason._tag===`BadResource`?t.succeed(d.none()):t.fail(new Te({cause:n,path:e})))),P=(e,n)=>S.FileSystem.pipe(t.flatMap(t=>t.writeFileString(e,n)),t.mapError(t=>new Ee({cause:t,path:e}))),F=(e,t)=>P(e,`${JSON.stringify(t,null,2)}\n`),I=(e,n)=>t.suspend(()=>{let r=[],i=te(e,r,{allowTrailingComma:!0});return r.length>0?t.fail(new Ce({errors:r,path:n})):t.succeed(i)}),L=e=>b.isObject(e),Ve=e=>Array.isArray(e),He=(e,n)=>t.try({catch:e=>new Se({cause:e}),try:()=>ie(e,n)}),Ue=/^workspace:/,We=/^[\^~]/;function Ge(e){return e.trim().replace(Ue,``).replace(We,``)}const R=(e=f.cwd())=>t.gen(function*(){let t=(yield*C.Path).join(e,`package.json`),n=yield*M(t);return yield*I(n,t)}),Ke=(e,n)=>t.gen(function*(){let t=yield*C.Path;yield*F(t.join(e,`package.json`),n)});function qe(e){return e===`bun`||e===`deno`||e===`npm`||e===`pnpm`||e===`yarn`}const z={analyze:`adamantite analyze`,check:`adamantite check`,fix:`adamantite fix`};function Je(e){let t=e.scripts??{};return y(re.keys(z),s.filter(e=>t[e]===z[e]))}function Ye(e,t){let n=e.scripts??{};return s.filterMap(t,e=>{let t=n[e];return t!==void 0&&t!==``&&t!==z[e]?_.succeed({command:t,script:e}):_.failVoid})}const Xe=/^(?:packages|"packages"|'packages')\s*:/u;function Ze(e){return e.replace(/(?:^|\s+)#.*$/u,``).trim()}function Qe(e){let t=e.replace(/^\uFEFF/u,``).split(/\r?\n/u),n=t.findIndex(e=>Xe.test(e));if(n===-1)return!1;let r=Ze((t[n]??``).replace(Xe,``));if(r===`[`){for(let e of t.slice(n+1)){let t=Ze(e);if(t.length!==0)return t!==`]`}return!1}if(r&&!r.startsWith(`#`))return!/^\[\s*\]$/u.test(r);for(let e of t.slice(n+1)){if(/^\s*-\s*[^#\s]/u.test(e))return!0;if(/^\S/u.test(e)&&!e.startsWith(`#`))return!1}return!1}const B=(e=f.cwd())=>t.gen(function*(){let t=yield*C.Path,n=yield*N(t.join(e,`pnpm-workspace.yaml`));if(d.isSome(n)&&Qe(n.value))return!0;let r=(yield*R(e)).workspaces;return((s.isArray(r)?r:r?.packages)?.length??0)>0});function $e(e){return e.replace(/^(["'])(.*)\1$/u,`$2`)}function et(e){let t=e.replace(/^\uFEFF/u,``).split(/\r?\n/u),n=t.findIndex(e=>Xe.test(e));if(n===-1)return[];let r=Ze((t[n]??``).replace(Xe,``));if(r.startsWith(`[`)){let e=[r,...t.slice(n+1).map(e=>Ze(e))].join(` `),i=e.indexOf(`]`);return e.slice(1,i===-1?void 0:i).split(`,`).map(e=>$e(e.trim())).filter(e=>e.length>0)}let i=[];for(let e of t.slice(n+1)){let t=/^\s*-\s*(.+)$/u.exec(Ze(e))?.[1];if(t!==void 0)i.push($e(t.trim()));else if(/^\S/u.test(e)&&!e.startsWith(`#`))break}return i}function tt(e){return e.replaceAll(/[$()+.[\\\]^{|}]/gu,String.raw`\$&`)}function nt(e){let t=e.replace(/^\.\//u,``).replace(/\/+$/u,``).split(`/`),n=``;for(let[e,r]of t.entries()){let i=e===0||t[e-1]===`**`?``:`/`;r===`**`?e<t.length-1?n+=`${i}(?:[^/]+/)*`:n+=e===0?`(?:[^/]+(?:/[^/]+)*)?`:`(?:/[^/]+)*`:n+=`${i}${tt(r).replaceAll(`*`,`[^/]*`).replaceAll(`?`,`[^/]`)}`}return RegExp(`^${n}$`,`u`)}function rt(e){let t=e.replace(/^\.\//u,``).replace(/\/+$/u,``).split(`/`),n=t.findIndex(e=>/[*?]/u.test(e));return n===-1?{base:t.join(`/`),depth:0}:{base:t.slice(0,n).join(`/`),depth:t.includes(`**`)?1/0:t.length-n}}const it=/* @__PURE__ */ new Set([`node_modules`]),at=(e,n,r)=>t.gen(function*(){let i=yield*C.Path,a=yield*Be(i.resolve(e,n));return d.isNone(a)?[]:r===0?[n]:[n,...(yield*t.forEach(a.value.filter(e=>!e.startsWith(`.`)&&!it.has(e)),t=>at(e,n===``?t:`${n}/${t}`,r-1),{concurrency:`unbounded`})).flat()]}),ot=(e=f.cwd())=>t.gen(function*(){let n=yield*C.Path,r=yield*N(n.join(e,`pnpm-workspace.yaml`)),i=(yield*R(e)).workspaces,a=d.match(r,{onNone:()=>s.isArray(i)?i:i?.packages??[],onSome:e=>et(e)}),o=a.filter(e=>!e.startsWith(`!`)),c=a.filter(e=>e.startsWith(`!`)).map(e=>nt(e.slice(1))),l=yield*t.forEach(o,n=>t.gen(function*(){let{base:t,depth:r}=rt(n),i=nt(n);return(yield*at(e,t,r)).filter(e=>e!==``&&i.test(e))}),{concurrency:`unbounded`}),u=s.dedupe(l.flat()).filter(e=>!c.some(t=>t.test(e)));return(yield*t.forEach(u,r=>N(n.join(e,r,`package.json`)).pipe(t.map(t=>d.isSome(t)?[n.resolve(e,r)]:[])),{concurrency:`unbounded`})).flat()});function st(e){return e.endsWith(`.jsonc`)?`jsonc`:e.endsWith(`.json`)?`json`:`ts`}function ct(e,t){return s.findFirst(e.legacyConfigs,e=>st(e)===t)}function lt(e){let t=ct(e,`json`),n=ct(e,`jsonc`);return y(d.zipWith(t,n,e=>`${e}(c)`),d.orElse(()=>n),d.orElse(()=>t),d.getOrElse(()=>``))}function ut(e,t,n,r){return n===null||r.length===0?[]:n.format===`ts`?[`Found both \`${t.config}\` and \`${lt(t)}\`. Adamantite will use \`${t.config}\`.`]:y(d.zipWith(ct(t,`json`),ct(t,`jsonc`),(t,n)=>`Found both \`${t}\` and \`${n}\`. Multiple legacy ${e} configs exist; Adamantite will treat \`${n}\` as the source of truth in its findings.`),d.toArray)}const dt=t.fn(`detectToolingConfig`)(function*(e,n,r){let i=yield*S.FileSystem,a=yield*C.Path,o=[r.config,...r.legacyConfigs].map(t=>({file:t,format:st(t),path:a.join(e,t)})),c=yield*t.forEach(o,e=>i.exists(e.path),{concurrency:`unbounded`}),l=o.filter((e,t)=>c[t]),u=y(s.findFirst(l,e=>e.format===`ts`),d.orElse(()=>s.findFirst(l,e=>e.format===`jsonc`)),d.orElse(()=>s.findFirst(l,e=>e.format===`json`)),d.getOrNull),f=l.filter(e=>e!==u&&e.format!==`ts`);return{active:u,legacy:f,warnings:ut(n,r,u,f)}});function ft(e,t,n){let r=e.devDependencies?.[t.name]??e.dependencies?.[t.name];return r?Ge(r)===t.version?[]:[{currentVersion:r,description:`Update \`${t.name}\` from \`${r}\` to \`${t.version}\`.`,package:t.name,targetVersion:t.version,type:`update_package`}]:[{description:`Install \`${t.name}@${t.version}\` for ${n}.`,package:t.name,targetVersion:t.version,type:`install_package`}]}function pt(e,t){return e.map(e=>({currentState:e.type===`install_package`?`The required package \`${e.package}\` is not installed.`:`The installed \`${e.package}\` version is \`${e.currentVersion}\`, but Adamantite requires \`${e.targetVersion}\`.`,goal:[`Run \`adamantite update\` so \`${e.package}@${e.targetVersion}\` is installed.`],id:`${e.type===`install_package`?`missing`:`outdated`}-${e.package}`,integration:t,title:e.type===`install_package`?`Missing ${e.package}`:`Outdated ${e.package}`}))}function mt(e,t){if(e.active===null)return[{currentState:`The managed \`${t.configFile}\` file is missing.`,goal:[`Create \`${t.configFile}\` with the reference content.`,`Do not create a legacy JSON or JSONC ${t.toolName} config.`],id:`missing-${t.toolName}-config`,integration:t.toolName,reference:{content:t.configContent,language:`ts`},title:`Missing ${t.toolName} configuration`}];if(e.active.format!==`ts`)return[{currentState:`Legacy \`${e.active.file}\` is the active ${t.toolName} configuration.`,goal:[`Port the project settings into \`${t.configFile}\` using the reference content as the base.`,`Delete every legacy ${t.toolName} JSON or JSONC config after its settings are preserved.`],id:`legacy-${t.toolName}-config`,integration:t.toolName,notes:[`Preserve project-specific settings. Do not replace them with the reference defaults.`],reference:{content:t.configContent,language:`ts`},title:`Legacy ${t.toolName} configuration`}];let n=[];return e.legacy.length>0&&n.push({currentState:`Legacy ${t.toolName} config files remain next to \`${t.configFile}\`: ${e.legacy.map(({file:e})=>`\`${e}\``).join(`, `)}.`,goal:[`Delete the legacy files after you confirm that \`${t.configFile}\` preserves their project-specific settings.`],id:`shadowed-legacy-${t.toolName}-config`,integration:t.toolName,title:`Legacy ${t.toolName} files remain`}),t.inspection?.kind===`invalid`&&n.push({currentState:`\`${t.configFile}\` does not meet Adamantite's required shape. ${t.inspection.reason}`,goal:[t.invalidGoal??t.inspection.goal??`Update \`${t.configFile}\` so it includes the required Adamantite preset while preserving project-specific settings.`],id:`invalid-${t.toolName}-config`,integration:t.toolName,notes:[`Treat the reference as a known-good example, not an exact replacement.`],reference:{content:t.configContent,language:`ts`},title:`Invalid ${t.toolName} configuration`}),n}function ht(e,t){let n=Je(e);return t.some(e=>n.includes(e))}function gt(e){return j({assess:(n,r)=>t.gen(function*(){let t=ht(r,e.scripts)&&(!e.monorepoOnly||(yield*B(n)))&&(e.isRequired===void 0||(yield*e.isRequired(n))),i=e.legacyFindings?.(r)??[];if(!t)return i.length>0?{applicable:!0,findings:[...i],packageActions:[],warnings:[]}:{applicable:!1,warnings:[]};let a=ft(r,e,e.purpose);return{applicable:!0,findings:[...pt(a,e.name),...i],packageActions:a,warnings:[]}}),kind:`tooling`,name:e.name,version:e.version})}const _t=t.fn(`detectToolingWorkspace`)(function*(e){return{isMonorepo:yield*B(e)}});function vt(e){let n=[{path:e.configFiles.config,type:`config`},...e.configFiles.legacyConfigs.map(e=>({path:e,type:`legacy_config`}))],r=t=>dt(t,e.name,e.configFiles);return j({assess:(n,i)=>t.gen(function*(){let t=e.legacyFindings?.(i)??[];if(!ht(i,e.scripts))return t.length>0?{applicable:!0,findings:t,packageActions:[],warnings:[]}:{applicable:!1,warnings:[]};let a=yield*r(n),o=ft(i,e,e.purpose),s=yield*e.detectWorkspace(n),c=e.configContent(s),l=a.active?.format===`ts`?e.inspectConfig(yield*M(a.active.path),s):void 0;return{applicable:!0,findings:[...pt(o,e.name),...mt(a,{configContent:c,configFile:e.configFiles.config,inspection:l,toolName:e.name}),...t],packageActions:o,warnings:a.warnings}}),config:e.configFiles.config,create:n=>t.gen(function*(){let t=yield*C.Path;yield*P(t.join(n,e.configFiles.config),e.configContent(yield*e.detectWorkspace(n)))}),detect:r,files:n,kind:`tooling`,name:e.name,version:e.version})}const yt=[`respectEslintDisableDirectives`,`typeAware`,`typeCheck`],bt="`oxlint.config.ts` must export an object literal directly, with or without `defineConfig(...)`, for Adamantite to inspect `options`.",xt="`oxlint.config.ts` has an `options` property, but it is not an object literal that Adamantite can inspect.",St=[`react`,`react-strict`,`react-doctor`,`tanstack`,`nextjs`,`vue`,`effect`,`jest`,`vitest`,`node`,`strict`,`antislop`,`shadcn`];function Ct(e){return e.replaceAll(/-([a-z])/g,(e,t)=>t.toUpperCase())}function wt(e=[]){let t=e.includes(`core`)?e:[`core`,...e];return[`import { defineConfig } from "oxlint"`,...t.map(e=>`import ${Ct(e)} from "${e===`core`?`adamantite/lint`:`adamantite/lint/${e}`}"`),`import custom from "adamantite/lint/custom"`,``,`export default defineConfig({`,` extends: [${[...t.map(e=>Ct(e)),`custom()`].join(`, `)}],`,` ignorePatterns: core.ignorePatterns,`,` options: {`,...yt.map(e=>` ${e}: true,`),` },`,`})`,``].join(`
|
|
6
|
-
`)
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
`);for(let[e,r]of n.entries()){let i=Hn.exec(r);if(!i)continue;let a=i[1]?.length??0,o=(i[2]??``).trim();if(t.test(o))return!0;if(Rn.test(o))for(let r of n.slice(e+1)){let e=r.trim();if(e.length!==0){if(r.length-r.trimStart().length<=a)break;if(t.test(e))return!0}}}return!1}function Wn(e){return` - name: Setup Node.js
|
|
1
|
+
import*as e from"@effect/platform-node/NodeRuntime";import*as t from"effect/Effect";import*as n from"effect/Exit";import*as r from"effect/process/ChildProcessSpawner";import*as i from"effect/Runtime";import*as a from"effect/Stdio";import*as o from"@effect/platform-node/NodeServices";import*as s from"effect/Array";import*as c from"effect/cli/Command";import*as l from"effect/Layer";import*as u from"effect/cli/Flag";import*as d from"effect/Option";import f from"node:process";import{stripVTControlCharacters as p,styleText as m}from"node:util";import*as h from"effect/Console";import*as g from"effect/Context";import*as _ from"effect/process/ChildProcess";import*as v from"effect/Result";import*as y from"effect/Data";import{pipe as b}from"effect/Function";import*as x from"effect/Predicate";import*as S from"effect/String";import{applyEdits as ee,findNodeAtLocation as te,modify as ne,parse as re,parseTree as ie,printParseErrorCode as ae,visit as oe}from"jsonc-parser";import*as C from"effect/FileSystem";import*as w from"effect/Path";import*as se from"effect/Record";import{defu as ce}from"defu";import*as le from"effect/Equal";import{Visitor as ue,parseSync as de}from"oxc-parser";import*as T from"effect/cli/Argument";import{addDevDependency as fe,detectPackageManager as pe,runScriptCommand as me}from"nypm";import*as E from"effect/Schema";import*as D from"effect/Order";import{delimiter as he}from"node:path";import*as ge from"effect/Config";import*as O from"@clack/prompts";import*as _e from"effect/Terminal";function ve(e){return x.isError(e)?b(p(e.message),S.split(/\r\n|[\r\n]/),s.map(e=>S.trimEnd(e)),s.filter(e=>S.isNonEmpty(e))):[]}function k(e){return b(ve(e),s.head,d.map(e=>{let t=S.trim(e);return/[.!?]$/.test(t)?` Cause: ${t}`:` Cause: ${t}.`}),d.getOrElse(()=>``))}function ye(e){let t=ve(e);if(!s.isReadonlyArrayNonEmpty(t))return``;let n=s.takeRight(t,20);return`\n${(n.length<t.length?[`…`,...n]:n).join(`
|
|
2
|
+
`)}`}function be(e=[]){return e.length===0?`- Unknown JSON/JSONC parsing error`:e.slice(0,3).map(e=>`- ${ae(e.error)} (offset: ${e.offset})`).join(`
|
|
3
|
+
`)}var xe=class extends y.TaggedError(`CliNotFound`){get message(){return`Command \`${this.command}\` not found. ${this.hint??`Please install it and try again.`}`}},Se=class extends y.TaggedError(`CommandFailed`){get message(){return`Command \`${this.command}\` failed with exit code ${this.exitCode}.`}},Ce=class extends y.TaggedError(`CustomRuleExists`){get message(){return`The custom rule \`${this.path}\` already exists. Choose another name or edit the file.`}},we=class extends y.TaggedError(`FailedToCreateDirectory`){get message(){return`Failed to create directory ${this.path?`\`${this.path}\``:`the target directory`}.${k(this.cause)}`}},Te=class extends y.TaggedError(`FailedToInstallDependency`){get message(){return`Failed to install dependencies${this.packages?.length?`: ${this.packages.join(`, `)}`:``}.${ye(this.cause)}`}},Ee=class extends y.TaggedError(`FailedToInstallExtension`){get message(){let e=this.extension?`\`${this.extension}\``:`the target extension`;return x.isNumber(this.cause)?`Failed to install ${e}. The \`code\` CLI exited with code ${this.cause}.`:`Failed to install ${e}.${k(this.cause)}`}},De=class extends y.TaggedError(`FailedToMergeConfig`){get message(){return`Failed to merge configuration.${k(this.cause)}`}},Oe=class extends y.TaggedError(`FailedToParseFile`){get message(){return[`Failed to parse ${this.path?`\`${this.path}\``:`the target file`}.`,`Please fix the JSON/JSONC syntax and run the command again.`,``,`Parse details:`,be(this.errors)].join(`
|
|
4
|
+
`)}},ke=class extends y.TaggedError(`FailedToParseSource`){get message(){return[`Failed to parse \`${this.path}\`.`,...this.errors.map(e=>`- ${e}`)].join(`
|
|
5
|
+
`)}},Ae=class extends y.TaggedError(`FailedToReadFile`){get message(){return`Failed to read ${this.path?`\`${this.path}\``:`the target file`}.${k(this.cause)}`}},je=class extends y.TaggedError(`FailedToWriteFile`){get message(){return`Failed to write ${this.path?`\`${this.path}\``:`the target file`}.${k(this.cause)}`}},Me=class extends y.TaggedError(`InvalidConfigFormat`){get message(){return`Invalid config format in ${this.path?`\`${this.path}\``:`the target config file`}. The config must be a JSON object (for example: {}).`}},Ne=class extends y.TaggedError(`InvalidAnalyzeOptions`){get message(){return`Invalid analyze options. ${this.reason}`}},Pe=class extends y.TaggedError(`InvalidFixOptions`){get message(){return`Invalid fix options. ${this.reason}`}},A=class extends y.TaggedError(`InvalidInitOptions`){get message(){return`Invalid init options. ${this.reason}`}},Fe=class extends y.TaggedError(`InvalidRuleName`){get message(){return`Invalid rule name \`${this.rule}\`. Use kebab-case that starts with a letter, such as \`no-process-env\`.`}},Ie=class extends y.TaggedError(`NoPackageManager`){get message(){return`No package manager detected. Please run this command from a project with a lockfile.${k(this.cause)}`}};y.TaggedError(`MissingPackageVersion`);var Le=class extends y.TaggedError(`OperationCancelled`){get message(){return`Operation cancelled.${this.reason?` Reason: ${this.reason}`:``}`}},Re=class extends y.TaggedError(`PassthroughNotSupported`){get message(){return`Command \`adamantite ${this.command}\` does not invoke a single underlying CLI and cannot accept passthrough arguments.`}},ze=class extends y.TaggedError(`VscodeCliNotFound`){get message(){return`VS Code CLI (\`code\`) not found. Please install it to manage extensions.${k(this.cause)}`}};const Be=(e,t)=>h.log(`${m(`bold`,e)} ${m(`dim`,`· adamantite (${t})`)}`),Ve=()=>[f.env.NODE_OPTIONS,`--disable-warning=MODULE_TYPELESS_PACKAGE_JSON`].filter(Boolean).join(` `),He=t.fn(`CommandRunner.exitCode`)(function*({args:e,command:n,cwd:r,detached:i,env:a,stderr:o=`inherit`,stdin:s=`ignore`,stdout:c=`inherit`}){return yield*t.scoped(t.gen(function*(){return yield*(yield*_.make(n,e,{cwd:r,detached:i,env:{...a,NODE_OPTIONS:Ve()},extendEnv:!0,stderr:o,stdin:s,stdout:c})).exitCode})).pipe(t.mapError(e=>e.reason._tag===`NotFound`?new xe({command:n}):e))});var j=class e extends g.Service()(`CommandRunner`){static make(e){let n=t.fn(`CommandRunner.run`)(function*(t){t.title!==void 0&&(yield*Be(t.title,t.command));let n=yield*e(t);if(n!==r.ExitCode(0))return yield*new Se({command:t.command,exitCode:n})}),i=e=>e.map((e,r)=>r===0?n(e):t.andThen(h.log(``),n(e)));return{exitCode:e,run:n,runAll:t.fn(`CommandRunner.runAll`)(function*(e){let n=yield*t.all(i(e),{concurrency:1,mode:`result`});yield*t.fromResult(v.all(n))}),runUntilFailure:t.fn(`CommandRunner.runUntilFailure`)(function*(e){yield*t.all(i(e),{concurrency:1,discard:!0})})}}static layer=l.effect(this)(t.gen(function*(){let n=yield*r.ChildProcessSpawner;return e.make(e=>He(e).pipe(t.provideService(r.ChildProcessSpawner,n)))}))};const Ue=g.Reference(`adamantite/ForwardedArguments`,{defaultValue:()=>[]});function M(e){return e}const We=e=>C.FileSystem.pipe(t.flatMap(t=>t.makeDirectory(e,{recursive:!0})),t.mapError(t=>new we({cause:t,path:e}))),N=e=>C.FileSystem.pipe(t.flatMap(t=>t.readFileString(e)),t.mapError(t=>new Ae({cause:t,path:e}))),P=e=>C.FileSystem.pipe(t.flatMap(t=>t.readFileString(e)),t.map(e=>b(e,d.some)),t.catch(n=>n.reason._tag===`NotFound`?t.succeedNone:t.fail(new Ae({cause:n,path:e})))),Ge=e=>C.FileSystem.pipe(t.flatMap(t=>t.readDirectory(e)),t.map(e=>b(e,d.some)),t.catch(n=>n.reason._tag===`NotFound`||n.reason._tag===`BadResource`?t.succeed(d.none()):t.fail(new Ae({cause:n,path:e})))),F=(e,n)=>C.FileSystem.pipe(t.flatMap(t=>t.writeFileString(e,n)),t.mapError(t=>new je({cause:t,path:e}))),Ke=(e,t)=>F(e,`${JSON.stringify(t,null,2)}\n`),I=(e,n)=>t.suspend(()=>{let r=[],i=re(e,r,{allowTrailingComma:!0});return r.length>0?t.fail(new Oe({errors:r,path:n})):t.succeed(i)}),L=e=>x.isObject(e),qe=e=>Array.isArray(e),Je=(e,n)=>t.try({catch:e=>new De({cause:e}),try:()=>ce(e,n)}),Ye=/^([ \t]+)"/mu;function Xe(e){let t=Ye.exec(e)?.[1]??` `,n=e.includes(`\r
|
|
6
|
+
`)?`\r
|
|
7
|
+
`:`
|
|
8
|
+
`;return t.startsWith(` `)?{eol:n,insertSpaces:!1,tabSize:1}:{eol:n,insertSpaces:!0,tabSize:t.length}}function Ze(e,t){return Object.hasOwn(e,t)?e[t]:void 0}function Qe(e,t,n){return L(e)&&L(t)?[...Object.keys(e),...Object.keys(t).filter(t=>!Object.hasOwn(e,t))].flatMap(r=>Qe(Ze(e,r),Ze(t,r),[...n,r])):le.equals(e,t)?[]:[[n,t]]}const $e=/^(?<comma>[ \t]*,)?(?<comment>(?:[ \t]*(?:\/\/[^\r\n]*|\/\*[^\r\n]*?\*\/))+)/u;function et(e,t){let n=t.at(-1),r=ie(e),i=r&&te(r,t.slice(0,-1)),a=i?.type===`object`?(i.children??[]).filter(e=>e.children?.[0]?.value===n):[];return a.length>1?a[0]:void 0}function tt(e,t){let n=t.offset+t.length,r;oe(e,{onSeparator:(e,t)=>{r===void 0&&e===`,`&&t>=n&&(r=t)}});let i=r===void 0?e:e.slice(0,r)+e.slice(r+1),a=i.slice(0,t.offset)+i.slice(n),o=a.lastIndexOf(`
|
|
9
|
+
`,t.offset-1)+1,s=a.indexOf(`
|
|
10
|
+
`,t.offset),c=s===-1?a.length:s+1;return a.slice(o,c).trim()===``?a.slice(0,o)+a.slice(c):a}function nt(e,t){let n=e;for(let e of t.keys()){let r=t.slice(0,e+1);for(let e=et(n,r);e;e=et(n,r))n=tt(n,e)}return n}function rt(e,t,n,r){let i=e=>ee(e,ne(e,t,n,{formattingOptions:r})),a=ie(e),o=t.slice(0,-1),s=a&&te(a,o)?.children?.at(-1),c=s?.children?.[0]?.value;if(n===void 0||a===void 0||te(a,t)!==void 0||s?.type!==`property`||!x.isString(c))return i(e);let l=s.offset+s.length,u=$e.exec(e.slice(l));if(u?.groups?.comment===void 0)return i(e);let d=l+(u.groups.comma?.length??0),f=u.groups.comment,p=i(e.slice(0,d)+e.slice(d+f.length)),m=ie(p),h=m&&te(m,[...o,c])?.parent,g=h?h.offset+h.length:d,_=g+(/^[ \t]*,/u.exec(p.slice(g))?.[0].length??0);return p.slice(0,_)+f+p.slice(_)}function it(e,t){let n=re(e,[],{allowTrailingComma:!0}),r=Xe(e);return Qe(n,t,[]).reduce((e,[t,n])=>rt(nt(e,t),t,n,r),e)}const at=/^workspace:/,ot=/^[\^~]/;function st(e){return e.trim().replace(at,``).replace(ot,``)}const R=(e=f.cwd())=>t.gen(function*(){let t=(yield*w.Path).join(e,`package.json`),n=yield*N(t);return yield*I(n,t)}),ct=(e,n)=>t.gen(function*(){let t=(yield*w.Path).join(e,`package.json`),r=yield*N(t);yield*F(t,it(r,n))});function lt(e){return e===`bun`||e===`deno`||e===`npm`||e===`pnpm`||e===`yarn`}const z={analyze:`adamantite analyze`,check:`adamantite check`,fix:`adamantite fix`};function ut(e){let t=e.scripts??{};return b(se.keys(z),s.filter(e=>t[e]===z[e]))}function dt(e,t){let n=e.scripts??{};return s.filterMap(t,e=>{let t=n[e];return t!==void 0&&t!==``&&t!==z[e]?v.succeed({command:t,script:e}):v.failVoid})}const ft=/^(?:packages|"packages"|'packages')\s*:/u;function pt(e){return e.replace(/(?:^|\s+)#.*$/u,``).trim()}function mt(e){let t=e.replace(/^\uFEFF/u,``).split(/\r?\n/u),n=t.findIndex(e=>ft.test(e));if(n===-1)return!1;let r=pt((t[n]??``).replace(ft,``));if(r===`[`){for(let e of t.slice(n+1)){let t=pt(e);if(t.length!==0)return t!==`]`}return!1}if(r&&!r.startsWith(`#`))return!/^\[\s*\]$/u.test(r);for(let e of t.slice(n+1)){if(/^\s*-\s*[^#\s]/u.test(e))return!0;if(/^\S/u.test(e)&&!e.startsWith(`#`))return!1}return!1}const B=(e=f.cwd())=>t.gen(function*(){let t=yield*w.Path,n=yield*P(t.join(e,`pnpm-workspace.yaml`));if(d.isSome(n)&&mt(n.value))return!0;let r=(yield*R(e)).workspaces;return((s.isArray(r)?r:r?.packages)?.length??0)>0});function ht(e){return e.replace(/^(["'])(.*)\1$/u,`$2`)}function gt(e){let t=e.replace(/^\uFEFF/u,``).split(/\r?\n/u),n=t.findIndex(e=>ft.test(e));if(n===-1)return[];let r=pt((t[n]??``).replace(ft,``));if(r.startsWith(`[`)){let e=[r,...t.slice(n+1).map(e=>pt(e))].join(` `),i=e.indexOf(`]`);return e.slice(1,i===-1?void 0:i).split(`,`).map(e=>ht(e.trim())).filter(e=>e.length>0)}let i=[];for(let e of t.slice(n+1)){let t=/^\s*-\s*(.+)$/u.exec(pt(e))?.[1];if(t!==void 0)i.push(ht(t.trim()));else if(/^\S/u.test(e)&&!e.startsWith(`#`))break}return i}function _t(e){return e.replaceAll(/[$()+.[\\\]^{|}]/gu,String.raw`\$&`)}function vt(e){let t=e.replace(/^\.\//u,``).replace(/\/+$/u,``).split(`/`),n=``;for(let[e,r]of t.entries()){let i=e===0||t[e-1]===`**`?``:`/`;r===`**`?e<t.length-1?n+=`${i}(?:[^/]+/)*`:n+=e===0?`(?:[^/]+(?:/[^/]+)*)?`:`(?:/[^/]+)*`:n+=`${i}${_t(r).replaceAll(`*`,`[^/]*`).replaceAll(`?`,`[^/]`)}`}return RegExp(`^${n}$`,`u`)}function yt(e){let t=e.replace(/^\.\//u,``).replace(/\/+$/u,``).split(`/`),n=t.findIndex(e=>/[*?]/u.test(e));return n===-1?{base:t.join(`/`),depth:0}:{base:t.slice(0,n).join(`/`),depth:t.includes(`**`)?1/0:t.length-n}}const bt=/* @__PURE__ */ new Set([`node_modules`]),xt=(e,n,r)=>t.gen(function*(){let i=yield*w.Path,a=yield*Ge(i.resolve(e,n));return d.isNone(a)?[]:r===0?[n]:[n,...(yield*t.forEach(a.value.filter(e=>!e.startsWith(`.`)&&!bt.has(e)),t=>xt(e,n===``?t:`${n}/${t}`,r-1),{concurrency:`unbounded`})).flat()]}),St=(e=f.cwd())=>t.gen(function*(){let n=yield*w.Path,r=yield*P(n.join(e,`pnpm-workspace.yaml`)),i=(yield*R(e)).workspaces,a=d.match(r,{onNone:()=>s.isArray(i)?i:i?.packages??[],onSome:e=>gt(e)}),o=a.filter(e=>!e.startsWith(`!`)),c=a.filter(e=>e.startsWith(`!`)).map(e=>vt(e.slice(1))),l=yield*t.forEach(o,n=>t.gen(function*(){let{base:t,depth:r}=yt(n),i=vt(n);return(yield*xt(e,t,r)).filter(e=>e!==``&&i.test(e))}),{concurrency:`unbounded`}),u=s.dedupe(l.flat()).filter(e=>!c.some(t=>t.test(e)));return(yield*t.forEach(u,r=>P(n.join(e,r,`package.json`)).pipe(t.map(t=>d.isSome(t)?[n.resolve(e,r)]:[])),{concurrency:`unbounded`})).flat()});function Ct(e){return e.endsWith(`.jsonc`)?`jsonc`:e.endsWith(`.json`)?`json`:`ts`}function wt(e,t){return s.findFirst(e.legacyConfigs,e=>Ct(e)===t)}function Tt(e){let t=wt(e,`json`),n=wt(e,`jsonc`);return b(d.zipWith(t,n,e=>`${e}(c)`),d.orElse(()=>n),d.orElse(()=>t),d.getOrElse(()=>``))}function Et(e,t,n,r){return n===null||r.length===0?[]:n.format===`ts`?[`Found both \`${t.config}\` and \`${Tt(t)}\`. Adamantite will use \`${t.config}\`.`]:b(d.zipWith(wt(t,`json`),wt(t,`jsonc`),(t,n)=>`Found both \`${t}\` and \`${n}\`. Multiple legacy ${e} configs exist; Adamantite will treat \`${n}\` as the source of truth in its findings.`),d.toArray)}const Dt=t.fn(`detectToolingConfig`)(function*(e,n,r){let i=yield*C.FileSystem,a=yield*w.Path,o=[r.config,...r.legacyConfigs].map(t=>({file:t,format:Ct(t),path:a.join(e,t)})),c=yield*t.forEach(o,e=>i.exists(e.path),{concurrency:`unbounded`}),l=o.filter((e,t)=>c[t]),u=b(s.findFirst(l,e=>e.format===`ts`),d.orElse(()=>s.findFirst(l,e=>e.format===`jsonc`)),d.orElse(()=>s.findFirst(l,e=>e.format===`json`)),d.getOrNull),f=l.filter(e=>e!==u&&e.format!==`ts`);return{active:u,legacy:f,warnings:Et(n,r,u,f)}});function Ot(e,t,n){let r=e.devDependencies?.[t.name]??e.dependencies?.[t.name];return r?st(r)===t.version?[]:[{currentVersion:r,description:`Update \`${t.name}\` from \`${r}\` to \`${t.version}\`.`,package:t.name,targetVersion:t.version,type:`update_package`}]:[{description:`Install \`${t.name}@${t.version}\` for ${n}.`,package:t.name,targetVersion:t.version,type:`install_package`}]}function kt(e,t){return e.map(e=>({currentState:e.type===`install_package`?`The required package \`${e.package}\` is not installed.`:`The installed \`${e.package}\` version is \`${e.currentVersion}\`, but Adamantite requires \`${e.targetVersion}\`.`,goal:[`Run \`adamantite update\` so \`${e.package}@${e.targetVersion}\` is installed.`],id:`${e.type===`install_package`?`missing`:`outdated`}-${e.package}`,integration:t,title:e.type===`install_package`?`Missing ${e.package}`:`Outdated ${e.package}`}))}function At(e,t){if(e.active===null)return[{currentState:`The managed \`${t.configFile}\` file is missing.`,goal:[`Create \`${t.configFile}\` with the reference content.`,`Do not create a legacy JSON or JSONC ${t.toolName} config.`],id:`missing-${t.toolName}-config`,integration:t.toolName,reference:{content:t.configContent,language:`ts`},title:`Missing ${t.toolName} configuration`}];if(e.active.format!==`ts`)return[{currentState:`Legacy \`${e.active.file}\` is the active ${t.toolName} configuration.`,goal:[`Port the project settings into \`${t.configFile}\` using the reference content as the base.`,`Delete every legacy ${t.toolName} JSON or JSONC config after its settings are preserved.`],id:`legacy-${t.toolName}-config`,integration:t.toolName,notes:[`Preserve project-specific settings. Do not replace them with the reference defaults.`],reference:{content:t.configContent,language:`ts`},title:`Legacy ${t.toolName} configuration`}];let n=[];return e.legacy.length>0&&n.push({currentState:`Legacy ${t.toolName} config files remain next to \`${t.configFile}\`: ${e.legacy.map(({file:e})=>`\`${e}\``).join(`, `)}.`,goal:[`Delete the legacy files after you confirm that \`${t.configFile}\` preserves their project-specific settings.`],id:`shadowed-legacy-${t.toolName}-config`,integration:t.toolName,title:`Legacy ${t.toolName} files remain`}),t.inspection?.kind===`invalid`&&n.push({currentState:`\`${t.configFile}\` does not meet Adamantite's required shape. ${t.inspection.reason}`,goal:[t.invalidGoal??t.inspection.goal??`Update \`${t.configFile}\` so it includes the required Adamantite preset while preserving project-specific settings.`],id:`invalid-${t.toolName}-config`,integration:t.toolName,notes:[`Treat the reference as a known-good example, not an exact replacement.`],reference:{content:t.configContent,language:`ts`},title:`Invalid ${t.toolName} configuration`}),n}function jt(e,t){let n=ut(e);return t.some(e=>n.includes(e))}function Mt(e){return M({assess:(n,r)=>t.gen(function*(){let t=jt(r,e.scripts)&&(!e.monorepoOnly||(yield*B(n)))&&(e.isRequired===void 0||(yield*e.isRequired(n))),i=e.legacyFindings?.(r)??[];if(!t)return i.length>0?{applicable:!0,findings:[...i],packageActions:[],warnings:[]}:{applicable:!1,warnings:[]};let a=Ot(r,e,e.purpose);return{applicable:!0,findings:[...kt(a,e.name),...i],packageActions:a,warnings:[]}}),kind:`tooling`,name:e.name,version:e.version})}const Nt=t.fn(`detectToolingWorkspace`)(function*(e){return{isMonorepo:yield*B(e)}});function Pt(e){let n=[{path:e.configFiles.config,type:`config`},...e.configFiles.legacyConfigs.map(e=>({path:e,type:`legacy_config`}))],r=t=>Dt(t,e.name,e.configFiles);return M({assess:(n,i)=>t.gen(function*(){let t=e.legacyFindings?.(i)??[];if(!jt(i,e.scripts))return t.length>0?{applicable:!0,findings:t,packageActions:[],warnings:[]}:{applicable:!1,warnings:[]};let a=yield*r(n),o=Ot(i,e,e.purpose),s=yield*e.detectWorkspace(n),c=e.configContent(s),l=a.active?.format===`ts`?e.inspectConfig(yield*N(a.active.path),s):void 0;return{applicable:!0,findings:[...kt(o,e.name),...At(a,{configContent:c,configFile:e.configFiles.config,inspection:l,toolName:e.name}),...t],packageActions:o,warnings:a.warnings}}),config:e.configFiles.config,create:n=>t.gen(function*(){let t=yield*w.Path;yield*F(t.join(n,e.configFiles.config),e.configContent(yield*e.detectWorkspace(n)))}),detect:r,files:n,kind:`tooling`,name:e.name,version:e.version})}const Ft=[`respectEslintDisableDirectives`,`typeAware`,`typeCheck`],It="`oxlint.config.ts` must export an object literal directly, with or without `defineConfig(...)`, for Adamantite to inspect `options`.",Lt="`oxlint.config.ts` has an `options` property, but it is not an object literal that Adamantite can inspect.",Rt=[`react`,`react-strict`,`react-doctor`,`tanstack`,`nextjs`,`vue`,`effect`,`jest`,`vitest`,`node`,`strict`,`antislop`,`shadcn`];function zt(e){return e.replaceAll(/-([a-z])/g,(e,t)=>t.toUpperCase())}function Bt(e=[]){let t=e.includes(`core`)?e:[`core`,...e];return[`import { defineConfig } from "oxlint"`,...t.map(e=>`import ${zt(e)} from "${e===`core`?`adamantite/lint`:`adamantite/lint/${e}`}"`),`import custom from "adamantite/lint/custom"`,``,`export default defineConfig({`,` extends: [${[...t.map(e=>zt(e)),`custom()`].join(`, `)}],`,` ignorePatterns: core.ignorePatterns,`,` options: {`,...Ft.map(e=>` ${e}: true,`),` },`,`})`,``].join(`
|
|
11
|
+
`)}const Vt=d.liftThrowable(e=>de(`oxlint.config.ts`,e,{astType:`ts`,lang:`ts`,sourceType:`module`}));function Ht(e){return Vt(e).pipe(d.flatMap(e=>e.errors.length===0?d.fromNullishOr(e.program):d.none()))}const Ut=`adamantite/lint/`,Wt=`${Ut}custom`;function Gt(e){return b(Ht(e),d.map(e=>e.body.flatMap(e=>e.type===`ImportDeclaration`&&e.source.value.startsWith(Ut)&&e.source.value!==Wt?[e.source.value.slice(16)]:[])),d.getOrElse(()=>[]))}function Kt(e){return e.type===`Identifier`?b(e.name,d.some):e.type===`Literal`&&x.isString(e.value)?b(e.value,d.some):d.none()}function qt(e){return e.type===`ObjectExpression`?b(e,d.some):e.type!==`CallExpression`||e.callee.type!==`Identifier`||e.callee.name!==`defineConfig`?d.none():b(e.arguments.length===1?s.head(e.arguments):d.none(),d.filter(e=>e.type===`ObjectExpression`))}function Jt(e){return b(e.body,s.filter(e=>e.type===`ExportDefaultDeclaration`),e=>e.length===1?s.head(e):d.none(),d.flatMap(e=>qt(e.declaration)))}function Yt(e,t){let n=null;for(let r of e.properties){if(r.type===`SpreadElement`||r.computed)return{status:`invalid`};let e=d.contains(Kt(r.key),t);if(r.method||r.kind!==`init`){if(e)return{status:`invalid`}}else if(e){if(n)return{status:`invalid`};n=r}}return n?{property:n,status:`found`}:{status:`missing`}}function Xt(e){for(let t of Ft){let n=Yt(e,t);if(n.status===`invalid`)return{kind:`invalid`,reason:"`oxlint.config.ts` has an `options` object Adamantite cannot inspect. Make sure each required option is a plain `key: true | false` property. Avoid spreads (`...rest`), computed keys (`[name]: ...`), duplicate keys, methods/getters/setters, and non-boolean-literal values."};if(n.status===`missing`||n.property.value.type!==`Literal`||n.property.value.value!==!0)return{kind:`invalid`,reason:`The required Oxlint options are missing or are not set to true.`}}return{kind:`configured`}}function Zt(e){let t=Ht(e);if(d.isNone(t))return{kind:`invalid`,reason:It};let n=Jt(t.value);if(d.isNone(n))return{kind:`invalid`,reason:It};let r=Yt(n.value,`options`);return r.status===`invalid`?{kind:`invalid`,reason:Lt}:r.status===`missing`?{kind:`invalid`,reason:`The required Oxlint options are missing.`}:r.property.value.type===`ObjectExpression`?Xt(r.property.value):{kind:`invalid`,reason:Lt}}function Qt(e,t){for(let n of e.body)if(n.type===`ImportDeclaration`&&n.source.value===t){for(let e of n.specifiers)if(e.type===`ImportDefaultSpecifier`)return e.local.name}return null}function $t(e,t){for(let n of e.body)if(n.type===`VariableDeclaration`){for(let e of n.declarations)if(e.id.type===`Identifier`&&e.id.name===t)return e.init}return null}function en(e,t,n){let r=!1;return new ue({Identifier:e=>{e.start>=n.start&&e.end<=n.end&&e.name===t&&(r=!0)}}).visit(e),r}function tn(e,t){let n=e.body.filter(e=>e.type===`ExportDefaultDeclaration`);if(n.length!==1)return!1;let r=n[0]?.declaration;if(!r)return!1;if(r.type!==`Identifier`)return en(e,t,r);if(r.name===t)return!0;let i=$t(e,r.name);return i!==null&&en(e,t,i)}function nn(e,t){let n=de(`config.ts`,e,{astType:`ts`,lang:`ts`,sourceType:`module`});if(n.errors.length>0)return{kind:`invalid`,reason:`The file is not valid TypeScript.`};let r=Qt(n.program,t.moduleName);return r?tn(n.program,r)?{kind:`configured`}:{kind:`invalid`,reason:`The imported ${t.presetName} preset is not used by the exported configuration.`}:{kind:`invalid`,reason:`The file must import the ${t.presetName} preset from \`${t.moduleName}\`.`}}const rn={isMonorepo:!1,usesEffectPreset:!1},an={effect:/ignoreDependencies\s*:\s*\[[^\]]*?@effect\/language-service/u,monorepo:/ignoreDependencies\s*:\s*\[[^\]]*?sherif/u},on={effect:/ignoreDependencies\s*:\s*(?:ignoreDependencies\.effect|\[[^\]]*?ignoreDependencies\.effect)/u,monorepo:/ignoreDependencies\s*:\s*(?:ignoreDependencies\.monorepo|\[[^\]]*?ignoreDependencies\.monorepo)/u},sn=/import\s[^;]*?\{[^}]*\bignoreDependencies\b[^}]*\}\s*from\s*["']adamantite\/analyze["']/u,cn={effect:"the `effect` lint preset names the `@effect/language-service` plugin in `tsconfig.json`, and no package has that name",monorepo:"Knip cannot see that `adamantite analyze` runs Sherif in a monorepo"};function ln(e){return[`monorepo`,`effect`].filter(t=>t===`monorepo`?e.isMonorepo:e.usesEffectPreset)}function un(e,t){return an[t].test(e)||on[t].test(e)&&sn.test(e)}function dn(e){let[t]=e;return e.length===1&&t!==void 0?`ignoreDependencies.${t}`:`[${e.map(e=>`...ignoreDependencies.${e}`).join(`, `)}]`}const fn=t.fn(`detectKnipWorkspace`)(function*(e){let t=yield*w.Path,n=yield*P(t.join(e,`oxlint.config.ts`));return{...yield*Nt(e),usesEffectPreset:d.match(n,{onNone:()=>!1,onSome:e=>Gt(e).includes(`effect`)})}});function pn(e,t){let n=nn(e,{moduleName:`adamantite/analyze`,presetName:`Adamantite analyze`});if(n.kind!==`configured`)return n;let r=ln(t),i=r.filter(t=>!un(e,t));if(i.length===0)return n;let a=`\`ignoreDependencies: ${dn(r)}\``;return{goal:`Set ${a} in \`knip.config.ts\`, with the named \`ignoreDependencies\` import from \`adamantite/analyze\`, and keep the other settings.`,kind:`invalid`,reason:`The file must set ${a} from \`adamantite/analyze\`, because ${i.map(e=>cn[e]).join(`, and `)}.`}}function mn(e=rn){let t=ln(e);return[`import type { KnipConfig } from "knip"`,t.length>0?`import analyze, { ignoreDependencies } from "adamantite/analyze"`:`import analyze from "adamantite/analyze"`,``,...t.length>0?[`const config: KnipConfig = {`,` ...analyze,`,` ignoreDependencies: ${dn(t)},`,`}`]:[`const config: KnipConfig = analyze`],``,`export default config`,``].join(`
|
|
12
|
+
`)}var V=Pt({configContent:mn,configFiles:{config:`knip.config.ts`,legacyConfigs:[`knip.json`,`knip.jsonc`]},detectWorkspace:fn,inspectConfig:pn,name:`knip`,purpose:"the managed `analyze` script",scripts:[`analyze`],version:`6.42.0`});const hn=/* @__PURE__ */ new Set([`check:monorepo`,`fix:monorepo`]),gn=/^adamantite\s+monorepo(?:\s|$)/u,_n=/* @__PURE__ */ new Map([[`--fail-on-warnings`,{key:`failOnWarnings`,takesValue:!1}],[`--ignore-dependency`,{key:`ignoreDependency`,takesValue:!0}],[`--ignore-package`,{key:`ignorePackage`,takesValue:!0}],[`--ignore-rule`,{key:`ignoreRule`,takesValue:!0}],[`--no-install`,{key:`noInstall`,takesValue:!1}],[`--select`,{key:`select`,takesValue:!0}],[`-i`,{key:`ignoreDependency`,takesValue:!0}],[`-p`,{key:`ignorePackage`,takesValue:!0}],[`-r`,{key:`ignoreRule`,takesValue:!0}],[`-s`,{key:`select`,takesValue:!0}]]);function vn(e){return Object.entries(e.scripts??{}).flatMap(([e,t])=>t!==void 0&&(hn.has(e)||gn.test(t.trim()))?[{command:t,name:e}]:[])}function yn(e){let t=e.command.trim().split(/\s+/u),n=[];for(let[e,r]of t.entries()){let[i=r,a]=r.split(`=`,2),o=_n.get(i);if(!o)continue;if(!o.takesValue){n.push(`Set \`sherif.${o.key}\` to \`true\` in the root \`package.json\`.`);continue}let s=a??t[e+1];s!==void 0&&n.push(o.key===`select`?`Set \`sherif.select\` to \`"${s}"\` in the root \`package.json\`.`:`Add \`"${s}"\` to the \`sherif.${o.key}\` array in the root \`package.json\`.`)}return n}function bn(e){let t=vn(e);if(t.length===0)return[];let n=ut(e).includes(`analyze`);return[{currentState:`Legacy monorepo scripts are present in \`package.json\`: ${t.map(({command:e,name:t})=>`\`${t}\` (\`${e}\`)`).join(`, `)}.${n?``:" The project has no managed `analyze` script."}`,goal:[...n?[]:["Adopt the managed `analyze` script with `adamantite init --non-interactive --script analyze`. It runs Sherif in a detected monorepo."],...s.dedupe(t.flatMap(e=>yn(e))),...t.map(({name:e})=>`Remove the \`${e}\` script from \`package.json\`.`)],id:`legacy-monorepo-scripts`,integration:`sherif`,notes:["`adamantite analyze` replaces `check:monorepo`, and `adamantite analyze --only monorepo --fix` replaces `fix:monorepo`. `adamantite analyze --fix` without `--only` also lets Knip remove unused files and dependencies.","`adamantite analyze` runs Sherif without flags. Sherif reads project exceptions from the `sherif` field of the root `package.json`, with the CLI options in camelCase: `ignoreDependency`, `ignoreRule`, `ignorePackage`, `select`, `noInstall`, and `failOnWarnings`.","Doctor does not assess `AGENTS.md`. Remove the lines that mention the monorepo scripts from its Adamantite section."],title:`Legacy monorepo scripts`}]}var H=Mt({legacyFindings:bn,monorepoOnly:!0,name:`sherif`,purpose:"the managed `analyze` script in a monorepo",scripts:[`analyze`],version:`1.13.0`});const xn=[{command:H.name,fixArguments:[`--fix`],name:`monorepo`,stdin:`inherit`,strictArguments:[],title:`📦 Analyzing the monorepo`},{command:V.name,fixArguments:[`--fix`,`--allow-remove-files`],name:`unused`,stdin:`ignore`,strictArguments:[`--production`,`--strict`],title:`🧹 Analyzing unused code`}],Sn=u.Boolean(`fix`).pipe(u.withDefault(!1),u.withDescription(`Automatically fix issues in every stage that runs`)),Cn=u.Boolean(`strict`).pipe(u.withDefault(!1),u.withDescription(`Enable strict mode for the unused stage (knip)`)),wn=u.Literals(`only`,[`monorepo`,`unused`]).pipe(u.optional,u.withDescription("Run one stage: `monorepo` (sherif, monorepos only) or `unused` (knip). Arguments after `--` go to that stage"));var Tn=c.make(`analyze`,{fix:Sn,only:wn,strict:Cn}).pipe(c.withDescription(`Find monorepo issues using sherif, then unused dependencies, exports, and files using knip`),c.withExamples([{command:`adamantite analyze -- --directory packages/app`,description:`Run knip from a specific directory`},{command:`adamantite analyze --only monorepo --fix -- --select highest`,description:`Fix only the monorepo issues and use the highest version on a mismatch`}]),c.withHandler(({fix:e,only:n,strict:r})=>t.gen(function*(){let i=yield*Ue,a=yield*j,o=d.getOrUndefined(n),s=yield*B().pipe(t.catchTags({FailedToParseFile:()=>t.succeed(!1),FailedToReadFile:()=>t.succeed(!1)}));if(o===`monorepo`){if(r)return yield*new Ne({reason:"`--strict` applies to the unused stage. Remove it or `--only monorepo`."});if(!s)return yield*new Ne({reason:"`--only monorepo` needs a monorepo, and no monorepo was detected."})}let c=xn.filter(e=>o===void 0?e.name===`unused`||s:e.name===o),l=o??`unused`,u=c.map(t=>({args:[...e?t.fixArguments:[],...r?t.strictArguments:[],...t.name===l?i:[]],command:t.command,stdin:t.stdin,title:t.title}));yield*(e?a.runUntilFailure(u):a.runAll(u)).pipe(t.mapError(e=>e._tag===`CliNotFound`&&e.command===H.name?new xe({command:e.command,hint:"Run `adamantite update` to install it."}):e))})));function En(e){return nn(e,{moduleName:`adamantite/format`,presetName:`Adamantite format`})}function Dn(){return[`import { defineConfig } from "oxfmt"`,`import format from "adamantite/format"`,``,`export default defineConfig(format)`,``].join(`
|
|
13
|
+
`)}var U=Pt({configContent:Dn,configFiles:{config:`oxfmt.config.ts`,legacyConfigs:[`.oxfmtrc.json`,`.oxfmtrc.jsonc`]},detectWorkspace:Nt,inspectConfig:En,legacyFindings:e=>e.scripts?.format===`adamantite format`?[{currentState:"The legacy managed `format` script is present in `package.json`.",goal:["Remove the `format` script from `package.json`."],id:`legacy-format-script`,integration:`oxfmt`,notes:["The managed `check` script verifies formatting and the managed `fix` script applies it.","Doctor does not assess `AGENTS.md`. Remove the `format` line from its Adamantite section."],title:`Legacy format script`}]:[],name:`oxfmt`,purpose:"the managed `check` and `fix` scripts",scripts:[`check`,`fix`],version:`0.73.0`});const On=`oxlint.config.ts`,kn=`.oxlintrc.json`,An=[{path:On,type:`config`},{path:kn,type:`legacy_config`}],jn={config:On,legacyConfigs:[kn]},Mn=`1.88.0`,Nn=e=>Dt(e,`oxlint`,jn);var W=M({assess:(e,n)=>t.gen(function*(){let t=ut(n);if(!t.includes(`check`)&&!t.includes(`fix`))return{applicable:!1,warnings:[]};let r=yield*Nn(e),i=Ot(n,{name:`oxlint`,version:Mn},`the managed lint scripts`),a=r.active,o;a?.format===`ts`&&(o=Zt(yield*N(a.path)));let s=Bt();return{applicable:!0,findings:[...kt(i,`oxlint`),...At(r,{configContent:s,configFile:On,inspection:o,invalidGoal:"Set `respectEslintDisableDirectives`, `typeAware`, and `typeCheck` to `true` in the `options` object. Preserve every other project setting.",toolName:`oxlint`})],packageActions:i,warnings:r.warnings}}),config:On,create:(e,n=[])=>t.gen(function*(){let t=yield*w.Path,r=Bt(n);yield*F(t.join(e,On),r)}),detect:Nn,files:An,kind:`tooling`,name:`oxlint`,version:Mn});const Pn=T.File(`files`,{mustExist:!0}).pipe(T.withDescription(`Specific files to check (optional)`),T.variadic()),Fn=u.Literals(`only`,[`format`,`lint`]).pipe(u.optional,u.withDescription("Run one stage: `format` (oxfmt) or `lint` (oxlint). Arguments after `--` go to that stage"));var In=c.make(`check`,{files:Pn,only:Fn}).pipe(c.withDescription(`Check formatting, code issues, and type errors`),c.withHandler(({files:e,only:n})=>t.gen(function*(){let t=yield*Ue,r=yield*j,i=d.getOrUndefined(n),a=i??`lint`,o=[{args:[`--check`,...e],command:U.name,name:`format`,title:`✨ Checking formatting`},{args:[...e],command:W.name,name:`lint`,title:`🔍 Linting`}];yield*r.runAll(o.filter(e=>i===void 0||e.name===i).map(e=>({args:[...e.args,...e.name===a?t:[]],command:e.command,title:e.title})))})));const Ln=[`check`,`analyze`];function Rn(e,t){return Ln.filter(e=>t.includes(e)).map(t=>({command:me(e,t),name:t}))}function zn(e){return Ln.some(t=>e.includes(t))}var Bn=class extends g.Service()(`DependencyInstaller`){static layer=l.succeed(this)({addDevDependencies:t.fn(`DependencyInstaller.addDevDependencies`)((e,n,r)=>t.tryPromise({catch:t=>new Te({cause:t,packages:e}),try:()=>fe(e,{...r,cwd:n})}).pipe(t.asVoid)),detectPackageManager:t.fn(`DependencyInstaller.detectPackageManager`)(e=>t.tryPromise({catch:e=>new Ie({cause:e}),try:()=>pe(e)}).pipe(t.map(e=>e??null)))})};function Vn(e,t){return t&&e!==`npm`}const Hn=(e,n)=>t.gen(function*(){let t=yield*Bn,r=yield*B(e),i=yield*t.detectPackageManager(e);yield*t.addDevDependencies(n,e,{silent:!0,workspace:Vn(i?.name,r)})});function Un(e){return{_tag:`File`,path:e}}function Wn(e){return{_tag:`Version`,value:e}}const Gn=[`.node-version`,`.nvmrc`],Kn=E.Struct({volta:E.Struct({node:E.NonEmptyString})}),qn=E.Struct({engines:E.Struct({node:E.NonEmptyString})}),Jn=E.Struct({name:E.NonEmptyString,version:E.NonEmptyString});function Yn(e){return e.split(`
|
|
14
|
+
`).map(e=>e.split(`#`)[0]?.trim()??``).some(e=>/^node(?:js)?\s+\S/.test(e))}function Xn(e){return E.is(Jn)(e)&&e.name.toLowerCase()===`node`}function Zn(e){if(E.is(Kn)(e))return!0;if(x.isObject(e)&&x.isObject(e.devEngines)){let t=e.devEngines.runtime;if((Array.isArray(t)?t:[t]).some(e=>Xn(e)))return!0}return E.is(qn)(e)}var Qn=class extends g.Service()(`NodeVersionResolver`){static layer=l.effect(this,t.gen(function*(){let e=yield*C.FileSystem,n=yield*w.Path,r=(r,i)=>P(n.join(r,i)).pipe(t.provideService(C.FileSystem,e));return{resolve:t.fn(`NodeVersionResolver.resolve`)(function*(e){for(let t of Gn){let n=yield*r(e,t);if(d.exists(n,e=>S.isNonEmpty(e.trim())))return Un(t)}let t=yield*r(e,`.tool-versions`);if(d.exists(t,e=>Yn(e)))return Un(`.tool-versions`);let i=yield*r(e,`package.json`);return d.isSome(i)&&Zn(yield*I(i.value,n.join(e,`package.json`)))?Un(`package.json`):Wn(`lts/*`)})}}))};const $n=/^\s*node-version:\s*"?\d/m,er=/^[>|](?:[1-9][+-]?|[+-][1-9]?)?(?:\s+#.*)?$/,tr=/\b(?:(?:bun|npm|pnpm|yarn)(?:\s+(?!run\b)\S+)*\s+run\s+check|deno(?:\s+(?!task\b)\S+)*\s+task\s+check)\b/,nr=/\b(?:(?:bun|npm|pnpm|yarn)(?:\s+(?!run\b)\S+)*\s+run\s+format|deno(?:\s+(?!task\b)\S+)*\s+task\s+format)(?:\s+--)?\s+--check\b/,rr=/\b(?:(?:bun|npm|pnpm|yarn)(?:\s+(?!run\b)\S+)*\s+run\s+(?:check|fix):monorepo|deno(?:\s+(?!task\b)\S+)*\s+task\s+(?:check|fix):monorepo|adamantite\s+monorepo)(?=\s|$)/,ir=/^(\s*)(?:-\s*)?(?:command|run):\s*(.*)$/;function ar(e,t){let n=e.split(`
|
|
15
|
+
`);for(let[e,r]of n.entries()){let i=ir.exec(r);if(!i)continue;let a=i[1]?.length??0,o=(i[2]??``).trim();if(t.test(o))return!0;if(er.test(o))for(let r of n.slice(e+1)){let e=r.trim();if(e.length!==0){if(r.length-r.trimStart().length<=a)break;if(t.test(e))return!0}}}return!1}function or(e){return` - name: Setup Node.js
|
|
11
16
|
uses: actions/setup-node@v7
|
|
12
17
|
with:
|
|
13
|
-
${e._tag===`File`?`node-version-file: "${e.path}"`:`node-version: "${e.value}"`}`}function
|
|
18
|
+
${e._tag===`File`?`node-version-file: "${e.path}"`:`node-version: "${e.value}"`}`}function sr(e){return{bun:`${or(e)}
|
|
14
19
|
|
|
15
20
|
- name: Setup Bun
|
|
16
21
|
uses: oven-sh/setup-bun@v2
|
|
@@ -30,22 +35,22 @@ import*as e from"@effect/platform-node/NodeRuntime";import*as t from"effect/Effe
|
|
|
30
35
|
uses: denoland/setup-deno@v2
|
|
31
36
|
|
|
32
37
|
- name: Install dependencies
|
|
33
|
-
run: deno install --frozen`,npm:`${
|
|
38
|
+
run: deno install --frozen`,npm:`${or(e)}
|
|
34
39
|
cache: "npm"
|
|
35
40
|
|
|
36
41
|
- name: Install dependencies
|
|
37
42
|
run: npm ci`,pnpm:` - name: Setup pnpm
|
|
38
|
-
uses: pnpm/action-setup@
|
|
43
|
+
uses: pnpm/action-setup@v6
|
|
39
44
|
|
|
40
|
-
${
|
|
45
|
+
${or(e)}
|
|
41
46
|
cache: "pnpm"
|
|
42
47
|
|
|
43
48
|
- name: Install dependencies
|
|
44
|
-
run: pnpm install --frozen-lockfile`,yarn:`${
|
|
49
|
+
run: pnpm install --frozen-lockfile`,yarn:`${or(e)}
|
|
45
50
|
cache: "yarn"
|
|
46
51
|
|
|
47
52
|
- name: Install dependencies
|
|
48
|
-
run: yarn install --frozen-lockfile`}}function
|
|
53
|
+
run: yarn install --frozen-lockfile`}}function cr({packageManager:e,scripts:t},n){let r=Rn(e,t);return r.length===0?null:`${`name: adamantite
|
|
49
54
|
|
|
50
55
|
on:
|
|
51
56
|
push:
|
|
@@ -77,11 +82,11 @@ ${r.map(e=>` - name: ${e.name}\n command: ${e.command}`).joi
|
|
|
77
82
|
- name: Checkout
|
|
78
83
|
uses: actions/checkout@v7
|
|
79
84
|
|
|
80
|
-
${
|
|
85
|
+
${sr(n)[e]}
|
|
81
86
|
|
|
82
87
|
- name: Run \${{ matrix.name }}
|
|
83
|
-
run: \${{ matrix.command }}`}\n`}const
|
|
84
|
-
`).length}function
|
|
88
|
+
run: \${{ matrix.command }}`}\n`}const lr={currentState:"The workflow still runs the legacy `format` script with `--check`.",goal:["Remove the workflow step or matrix entry that runs the `format` script with `--check`."],id:`legacy-format-workflow-step`,integration:`github`,notes:["The managed `check` script verifies formatting. Preserve unrelated workflow jobs and project-specific settings."],title:`Legacy format workflow step`},ur={currentState:"The workflow still runs a legacy monorepo script or `adamantite monorepo`.",goal:["Remove the workflow step or matrix entry that runs `check:monorepo`, `fix:monorepo`, or `adamantite monorepo`.","Make the workflow run the managed `analyze` script. It runs Sherif in a detected monorepo."],id:`legacy-monorepo-workflow-step`,integration:`github`,notes:[`Preserve unrelated workflow jobs and project-specific settings.`],title:`Legacy monorepo workflow step`},dr=[{path:`.github/workflows/adamantite.yml`,type:`ci`}],fr=(e,n)=>t.gen(function*(){let t=yield*w.Path,r=yield*Qn,i=t.join(e,dr[0].path),a=cr(n,yield*r.resolve(e));a&&(yield*F(i,a))});var pr=M({assess:(e,n)=>t.gen(function*(){let t=(yield*w.Path).join(e,dr[0].path),r=yield*P(t);if(r._tag===`None`)return{applicable:!1,warnings:[]};let i=ut(n),a=$n.test(r.value),o=i.includes(`check`)&&!ar(r.value,tr),s=[...ar(r.value,nr)?[lr]:[],...ar(r.value,rr)?[ur]:[]];if(!a&&!o)return{applicable:!0,findings:s,packageActions:[],warnings:[]};if(!zn(i))return{applicable:!0,findings:s,packageActions:[],warnings:[`No CI-compatible managed scripts were found, so the GitHub Actions workflow cannot be regenerated.`]};let c=yield*(yield*Bn).detectPackageManager(e);return c?lt(c.name)?{applicable:!0,findings:[{currentState:[...a?[`The workflow contains a hard-coded Node.js version.`]:[],...o?["The workflow does not run the managed `check` script."]:[]].join(` `),goal:["Make the workflow run the managed `check` script.",`Use the project's Node.js version declaration instead of a hard-coded version.`],id:`outdated-adamantite-workflow`,integration:`github`,notes:[`The detected package manager is \`${c.name}\`. Preserve unrelated workflow jobs and project-specific settings.`],title:`Outdated Adamantite workflow`},...s],packageActions:[],warnings:[]}:{applicable:!0,findings:s,packageActions:[],warnings:[`\`${c.name}\` is not a supported package manager for CI workflow generation, so the GitHub Actions workflow cannot be regenerated.`]}:{applicable:!0,findings:s,packageActions:[],warnings:[`Could not detect a package manager, so the GitHub Actions workflow cannot be regenerated.`]}}),create:(e,n)=>t.gen(function*(){let t=yield*w.Path;yield*We(t.dirname(t.join(e,dr[0].path))),yield*fr(e,n)}),detect:e=>t.gen(function*(){let t=yield*C.FileSystem,n=yield*w.Path;return yield*t.exists(n.join(e,dr[0].path))}),files:dr,kind:`ci`,name:`github`,update:fr});const G=[{path:`.zed/settings.json`,type:`config`}],mr={languages:{Astro:{format_on_save:`on`,prettier:{allowed:!0,plugins:[`prettier-plugin-astro`]}},CSS:{format_on_save:`on`,formatter:[{language_server:{name:`oxfmt`}}],prettier:{allowed:!1}},HTML:{format_on_save:`on`,formatter:[{language_server:{name:`oxfmt`}}],prettier:{allowed:!1}},JSON:{format_on_save:`on`,formatter:[{language_server:{name:`oxfmt`}}],prettier:{allowed:!1}},JSONC:{format_on_save:`on`,formatter:[{language_server:{name:`oxfmt`}}],prettier:{allowed:!1}},JavaScript:{format_on_save:`on`,formatter:[{language_server:{name:`oxfmt`}},{code_action:`source.fixAll.oxc`}],prettier:{allowed:!1}},MDX:{format_on_save:`on`,formatter:[{language_server:{name:`oxfmt`}}],prettier:{allowed:!1}},Markdown:{format_on_save:`on`,formatter:[{language_server:{name:`oxfmt`}}],prettier:{allowed:!1}},TSX:{format_on_save:`on`,formatter:[{language_server:{name:`oxfmt`}},{code_action:`source.fixAll.oxc`}],prettier:{allowed:!1}},TypeScript:{format_on_save:`on`,formatter:[{language_server:{name:`oxfmt`}},{code_action:`source.fixAll.oxc`}],prettier:{allowed:!1}},YAML:{format_on_save:`on`,formatter:[{language_server:{name:`oxfmt`}}],prettier:{allowed:!1}}},lsp:{oxfmt:{initialization_options:{settings:{"fmt.configPath":null,run:`onSave`}}},oxlint:{initialization_options:{settings:{configPath:null,fixKind:`safe_fix`,run:`onType`,typeAware:!0,unusedDisableDirectives:`deny`}}}}},hr={configPath:null,"fmt.experimental":!0,typeAware:!1,unusedDisableDirectives:!1};function gr(e){let t=e.lsp,n=L(t)?t.oxfmt:void 0,r=L(n)?n.initialization_options:void 0,i=L(r)?r.settings:void 0;if(!L(i))return[];let a=Object.entries(hr);return Object.entries(i).filter(([e,t])=>a.some(([n,r])=>n===e&&r===t)).map(([e])=>e)}function _r(e){return!L(e)||!qe(e.plugins)?e:Object.fromEntries([...Object.entries(e),[`plugins`,s.dedupe(e.plugins)]])}function vr(e){let t=e.languages;if(!L(t))return e;let n=Object.fromEntries(Object.entries(t).map(([e,t])=>!(e in mr.languages)||!L(t)?[e,t]:[e,Object.fromEntries(Object.entries(t).map(([e,t])=>e===`formatter`&&qe(t)?[e,s.dedupe(t)]:e===`prettier`?[e,_r(t)]:[e,t]))]));return Object.fromEntries([...Object.entries(e),[`languages`,n]])}var K=M({assess:(e,n)=>t.gen(function*(){let t=(yield*w.Path).join(e,G[0].path),n=yield*P(t);if(n._tag===`None`)return{applicable:!1,warnings:[]};let r=yield*I(n.value,t),i=L(r)?gr(r):[];return{applicable:!0,findings:i.length===0?[]:[{currentState:`\`${G[0].path}\` contains stale oxfmt settings: ${i.map(e=>`\`${e}\``).join(`, `)}.`,goal:[`Remove only the stale oxfmt entries that still have Adamantite's old default values.`,`Preserve entries that the project changed.`],id:`legacy-zed-oxfmt-settings`,integration:`zed`,title:`Legacy Zed oxfmt settings`}],packageActions:[],warnings:[]}}),config:G[0].path,create:e=>t.gen(function*(){let t=yield*w.Path,n=t.join(e,G[0].path);yield*We(t.dirname(n)),yield*Ke(n,mr)}),detect:e=>t.gen(function*(){let t=yield*C.FileSystem,n=yield*w.Path;return yield*t.exists(n.join(e,G[0].path))}),files:G,kind:`editor`,name:`zed`,update:e=>t.gen(function*(){let t=(yield*w.Path).join(e,G[0].path),n=yield*N(t),r=yield*I(n,t);if(!x.isObject(r))return yield*new Me({path:t});let i=vr(yield*Je(mr,r));yield*F(t,it(n,i))})});const yr=`project`,br=`.adamantite/rules`,xr=/* @__PURE__ */ new Set([`.js`,`.mjs`,`.mts`,`.ts`]);function Sr(e){let t=/\.[^.]+$/.exec(e)?.[0]??``;return xr.has(t)&&!e.startsWith(`_`)&&!/\.d\.m?ts$/.test(e)}function Cr(e,t){return de(e,t,{preserveParens:!1,sourceType:`module`})}function wr(e,t){return e.body.flatMap(e=>e.type===`ImportDeclaration`&&e.source.value===t?e.specifiers:[]).find(e=>e.type===`ImportDefaultSpecifier`)?.local.name}function Tr(e){return e.type===`Literal`&&x.isString(e.value)?e.value:e.type===`TemplateLiteral`&&e.expressions.length===0?e.quasis[0]?.value.cooked??null:null}function Er(e){return e.type===`Literal`&&x.isString(e.value)?e.value:null}function Dr(e){let t=br,n=yr;for(let r of e.properties){if(r.type===`SpreadElement`||r.computed)return{dir:null,name:null};let e=r.key.type===`Identifier`?r.key.name:Er(r.key);e===`dir`?t=Tr(r.value):e===`name`&&(n=Tr(r.value))}return{dir:t,name:n}}function Or(e,t){let n=Cr(e,t),r=wr(n.program,`adamantite/lint/custom`);if(n.errors.length>0||r===void 0)return[];let i=[];return new ue({CallExpression(e){if(e.callee.type!==`Identifier`||e.callee.name!==r)return;let[t]=e.arguments;t===void 0?i.push({dir:br,name:yr}):t.type===`ObjectExpression`?i.push(Dr(t)):i.push({dir:null,name:null})}}).visit(n.program),i}function kr(e,t){return e.slice(0,t).split(`
|
|
89
|
+
`).length}function Ar(e){switch(e.type){case`TSInterfaceDeclaration`:case`TSTypeAliasDeclaration`:return!0;case`TSModuleDeclaration`:return jr(e);case`ClassDeclaration`:case`FunctionDeclaration`:case`TSEnumDeclaration`:case`VariableDeclaration`:return e.declare===!0;case`ExportNamedDeclaration`:return e.declaration===null?e.exportKind===`type`:Ar(e.declaration);default:return!1}}function jr(e){return e.kind===`global`||e.declare||e.body===null||e.body.body.every(e=>e.type!==`ExpressionStatement`&&Ar(e))}function Mr(e){return e.body.some(e=>e.type===`ExportDefaultDeclaration`?e.declaration.type!==`TSInterfaceDeclaration`:e.type===`ExportNamedDeclaration`&&e.exportKind!==`type`&&e.specifiers.some(e=>e.exportKind!==`type`&&(e.exported.type===`Literal`?e.exported.value==="default":e.exported.name==="default")))}function Nr(e,t){let n=Cr(e,t);return n.errors.length>0?[]:n.program.body.flatMap(e=>{switch(e.type){case`ImportDeclaration`:return e.importKind===`type`?[]:[e.source.value];case`ExportAllDeclaration`:case`ExportNamedDeclaration`:return e.source===null||e.exportKind===`type`?[]:[e.source.value];default:return[]}})}function Pr(e,t){let n=Cr(e,t);if(n.errors.length>0)return n.errors.map(e=>`Syntax error: ${e.message}`);let r=[],i=(e,n)=>{r.push(`Line ${kr(t,e)}: ${n} needs a TypeScript transform, which type stripping does not do.`)};return new ue({TSEnumDeclaration(e){e.declare||i(e.start,"`enum`")},TSExportAssignment(e){i(e.start,"`export =`")},TSImportEqualsDeclaration(e){e.importKind!==`type`&&i(e.start,"`import x = ...`")},TSModuleDeclaration(e){jr(e)||i(e.start,"A `namespace` with values")},TSParameterProperty(e){i(e.start,`A parameter property`)}}).visit(n.program),Mr(n.program)||r.push(`The file has no default export. Export the rule as default.`),r}const Fr=`.adamantite/rules`,Ir=/^[a-z][\da-z]*(?:-[\da-z]+)*$/;function Lr(e){return`import { defineRule } from "adamantite/rules"
|
|
85
90
|
|
|
86
91
|
export default defineRule({
|
|
87
92
|
meta: {
|
|
@@ -99,32 +104,32 @@ export default defineRule({
|
|
|
99
104
|
}
|
|
100
105
|
},
|
|
101
106
|
})
|
|
102
|
-
`}const
|
|
107
|
+
`}const Rr=t.fn(`addCustomRule`)(function*(e,n,r=Fr){if(!Ir.test(n))return yield*new Fe({rule:n});let i=yield*C.FileSystem,a=yield*w.Path,o=a.resolve(e,r),s=a.join(o,`${n}.ts`),c=a.join(o,`AGENTS.md`),l=e=>i.exists(e).pipe(t.mapError(t=>new Ae({cause:t,path:e})));return(yield*l(s))?yield*new Ce({path:s}):(yield*We(o),yield*F(s,Lr(n)),(yield*l(c))?{agentsPath:void 0,rulePath:s}:(yield*F(c,'# Custom rules\n\nEach file in the rules folder, `.adamantite/rules/` by default, is an Oxlint rule that this\nproject owns. `custom()` from `adamantite/lint/custom` loads the folder and enables each\nrule as `error` under the `project` plugin: `no-process-env.ts` becomes\n`project/no-process-env`. Add a file to add a rule. Delete the file to remove the rule.\n`adamantite rule add <name>` writes a correct stub.\n\n- A file that starts with `_`, such as `_helpers.ts`, is a helper, not a rule. Subfolders are\n not read.\n- Export the rule as default with `defineRule` from `adamantite/rules`. The same module exports\n the `Context`, `Rule`, `Visitor`, and `ESTree` node types.\n- Use `createOnce`. It runs one time for each lint run, not one time for each file. Reset\n per-file state in `before`, and report collected results in `after`. `context.filename`,\n `context.sourceCode`, and `context.settings` are not available in the body of\n `createOnce`. Read them in `before` or in a visitor.\n- Write erasable TypeScript only. Oxlint loads rule files with Node.js type stripping, so\n `enum`, a `namespace` with values, parameter properties, and `import x = require()` stop\n the lint run.\n- Rules get no type information. Use only the AST and `context.sourceCode`.\n- Report with a `messageId`, and put each message in `meta.messages`. Describe the options in\n `meta.schema`, and read them from `context.options`.\n- A rule that throws prints an error for each file, and the lint run still exits 0. After you\n change a rule, run the lint and read all of its output.\n- To find node names, run `adamantite rule ast <file>` on real code. It prints the same\n ESTree-shaped AST that rules visit.\n- To test a rule, use `RuleTester` from `oxlint/plugins-dev`. Adamantite does not run rule\n tests.\n- Oxlint caches the rules for each run. Restart the editor language server after you change a\n rule.\n- TypeScript does not check `.adamantite/rules/` by default, because its name starts with a dot. Add\n `".adamantite/rules"` to `include` in `tsconfig.json` to check it.\n- In a monorepo, give each rules folder its own plugin name, such as `custom({ name: "web" })`:\n Oxlint rejects two plugins with the same name in one run. A relative `dir` resolves from the\n file that calls `custom()`, so a shared tooling package can own the rules with\n `custom({ dir: "rules", name: "acme" })`. A nested Oxlint config replaces the root config, so\n a package that needs the root rules extends the root config.\n'),{agentsPath:c,rulePath:s}))}),zr=`custom-rules`,Br=[`oxlint.config.ts`,`oxlint.config.mts`,`oxlint.config.js`,`oxlint.config.mjs`],Vr=[`.ts`,`.mts`,`.cts`,`.js`,`.mjs`,`.cjs`],Hr=/* @__PURE__ */ new Set([`default`,`import`,`node`]);function Ur(e){if(e!=null)return x.isString(e)?e:s.isArray(e)?e.map(e=>Ur(e)).find(e=>e!==void 0):Object.entries(e).filter(([e])=>Hr.has(e)).map(([,e])=>Ur(e)).find(e=>e!==void 0)}const Wr=D.combine(D.mapInput(D.flip(D.Number),([e])=>e.indexOf(`*`)),D.mapInput(D.flip(D.Number),([e])=>e.length));function Gr(e,t){let{exports:n}=e;if(n===void 0)return t===``?e.main??`index`:t;let r=t===``?`.`:`./${t}`;if(n===null||x.isString(n)||s.isArray(n))return r===`.`?Ur(n):void 0;let i=Object.keys(n).some(e=>e.startsWith(`.`))?n:{".":n};if(r in i)return Ur(i[r]);let a=s.sort(Object.entries(i),Wr).map(([e,t])=>{let[n,i,...a]=e.split(`*`);return n!==void 0&&i!==void 0&&a.length===0&&r.startsWith(n)&&r.endsWith(i)&&r.length>n.length+i.length?{match:r.slice(n.length,r.length-i.length),target:t}:null}).find(e=>e!==null);return a===void 0?void 0:Ur(a.target)?.replaceAll(`*`,a.match)}const Kr=t.fn(`readWorkspacePackage`)(function*(e){let t=yield*R(e);return t.name===void 0?d.none():d.some({directory:e,exports:t.exports,main:t.main,name:t.name})}),qr=t.fn(`readFirstFile`)(function*(e){for(let n of e){let e=yield*P(n).pipe(t.orElseSucceed(()=>d.none()));if(d.isSome(e))return d.some({content:e.value,file:n})}return d.none()}),Jr=t.fn(`resolveImport`)(function*(e,t,n){let r=yield*w.Path,i;if(t.startsWith(`.`)||r.isAbsolute(t))i=r.resolve(r.dirname(e),t);else{let e=n.find(e=>t===e.name||t.startsWith(`${e.name}/`));if(e===void 0)return{_tag:`external`};let a=Gr(e,t.slice(e.name.length+1));if(a===void 0)return{_tag:`unresolved`};i=r.resolve(e.directory,a)}if(i.split(r.sep).includes(`node_modules`))return{_tag:`external`};let a=i,o=i.replace(/\.[cm]?js$/u,``),s=yield*qr([i,...Vr.map(e=>`${o}${e}`),...Vr.map(e=>r.join(a,`index${e}`))]);return d.match(s,{onNone:()=>({_tag:`unresolved`}),onSome:e=>({_tag:`found`,module:e})})}),Yr=t.fn(`findCustomRulesCalls`)(function*(e){let n=yield*w.Path,r=s.getSomes(yield*t.forEach(e,e=>Kr(e),{concurrency:`unbounded`})),i=s.getSomes(yield*t.forEach(e,e=>qr(Br.map(t=>n.join(e,t))),{concurrency:`unbounded`})),a=/* @__PURE__ */ new Set,o=[],c=[],l=i;for(;l.length>0;){let e=l.filter(e=>!a.has(e.file));for(let t of e)a.add(t.file),t.content.includes(`adamantite/lint/custom`)&&o.push(...Or(t.file,t.content).map(e=>({dir:e.dir===null?null:n.resolve(n.dirname(t.file),e.dir),name:e.name,source:t.file})));let i=e.flatMap(e=>Nr(e.file,e.content).map(t=>({from:e.file,specifier:t}))),s=yield*t.forEach(i,({from:e,specifier:t})=>Jr(e,t,r),{concurrency:`unbounded`});l=[];for(let[e,t]of s.entries()){let n=i[e];t._tag===`found`?l.push(t.module):t._tag===`unresolved`&&n!==void 0&&c.push(n)}}return{calls:o,unresolvedImports:c}}),Xr=t.fn(`readRulesFolder`)(function*(e){return(yield*Ge(e)).pipe(d.map(t=>({dir:e,ruleFiles:t.filter(e=>Sr(e))})))});var Zr=M({assess:e=>t.gen(function*(){let n=yield*w.Path,r=t=>n.relative(e,t)||`.`,i=[e,...(yield*B(e))?yield*St(e):[]],{calls:a,unresolvedImports:o}=yield*Yr(i),c=i.map(e=>n.join(e,Fr)),l=s.dedupe(a.flatMap(e=>e.dir===null?[]:[e.dir])),u=s.getSomes(yield*t.forEach(s.dedupe([...c,...l]),e=>Xr(e),{concurrency:`unbounded`})).filter(e=>e.ruleFiles.length>0);if(a.length===0&&u.length===0&&o.length===0)return{applicable:!1,warnings:[]};let d=a.filter(e=>e.dir===null||e.name===null),f=[...o.map(({from:e,specifier:t})=>`Doctor cannot resolve the import of \`${t}\` in \`${r(e)}\`, so it does not check the \`custom()\` calls and rules folders behind it.`),...d.map(e=>`Doctor cannot read the \`dir\` or \`name\` of a \`custom()\` call in \`${r(e.source)}\`, because it is not a string literal. Doctor does not check that rules folder.`)],p=[];if(d.length===0&&o.length===0)for(let e of u)l.includes(e.dir)||p.push({currentState:`\`${r(e.dir)}\` has ${e.ruleFiles.length} rule file(s), but no \`custom()\` call loads it, so Oxlint does not run them.`,goal:[`Load \`${r(e.dir)}\` with \`custom()\` from \`adamantite/lint/custom\` in the Oxlint config of \`${r(n.dirname(n.dirname(e.dir)))}\`. A relative \`dir\` resolves from the file that calls \`custom()\`.`,"Give each rules folder its own plugin name with the `name` option, because Oxlint rejects two plugins with the same name in one run.",`Preserve every other setting in the Oxlint config.`],id:`custom-rules-not-loaded:${r(e.dir)}`,integration:zr,reference:{content:`import { defineConfig } from "oxlint"
|
|
103
108
|
import core from "adamantite/lint"
|
|
104
109
|
import custom from "adamantite/lint/custom"
|
|
105
110
|
|
|
106
111
|
export default defineConfig({
|
|
107
112
|
extends: [core, custom()],
|
|
108
113
|
})
|
|
109
|
-
`,language:`ts`},title:`Custom rules in \`${r(e.dir)}\` are not loaded`});for(let e of u)for(let t of e.ruleFiles){let i=n.join(e.dir,t),a=
|
|
110
|
-
`)}`,goal:["The file parses, uses only TypeScript that type stripping can erase (no `enum`, `namespace` with values, parameter properties, or `import x = require()`), and exports the rule as default.",`Keep the behavior of the rule.`],id:`custom-rule-cannot-load:${r(i)}`,integration:
|
|
111
|
-
`)}function
|
|
114
|
+
`,language:`ts`},title:`Custom rules in \`${r(e.dir)}\` are not loaded`});for(let e of u)for(let t of e.ruleFiles){let i=n.join(e.dir,t),a=Pr(i,yield*N(i));a.length!==0&&p.push({currentState:`\`${r(i)}\` cannot load as a rule, so the whole lint run fails with "Failed to parse oxlint configuration file":\n${a.map(e=>` - ${e}`).join(`
|
|
115
|
+
`)}`,goal:["The file parses, uses only TypeScript that type stripping can erase (no `enum`, `namespace` with values, parameter properties, or `import x = require()`), and exports the rule as default.",`Keep the behavior of the rule.`],id:`custom-rule-cannot-load:${r(i)}`,integration:zr,notes:["A file that starts with `_` is a helper, not a rule. Rename a helper file so that it starts with `_`."],title:`Custom rule \`${r(i)}\` cannot load`})}let m=a.filter(e=>e.dir!==null&&u.some(t=>t.dir===e.dir)&&e.name!==null);for(let[e,t]of Object.entries(s.groupBy(m,e=>e.name??``))){let n=s.dedupe(t.map(e=>e.dir??``));n.length<2||p.push({currentState:`${n.length} rules folders use the plugin name \`${e}\`: ${n.map(e=>`\`${r(e)}\``).join(`, `)}. Oxlint rejects two plugins with the same name in one run.`,goal:[`Each \`custom()\` call that loads one of these folders passes a \`name\` that no other rules folder uses, such as \`custom({ name: "web" })\`. The calls are in ${s.dedupe(t.map(e=>`\`${r(e.source)}\``)).join(`, `)}.`,"Rule names in `oxlint-disable` comments and `rules` settings use the new plugin name."],id:`custom-rules-duplicate-name:${e}`,integration:zr,title:`Rules folders share the plugin name \`${e}\``})}return{applicable:!0,findings:p,packageActions:[],warnings:f}}),kind:`tooling`,name:zr});const Qr=t.fn(`checkImportsLintPreset`)(function*(e,t){let n=yield*w.Path,r=yield*P(n.join(e,`oxlint.config.ts`));return d.match(r,{onNone:()=>!1,onSome:e=>Gt(e).includes(t)})});function $r(e){let{assess:n,name:r,preset:i,version:a,...o}=e,s=Mt({isRequired:e=>Qr(e,i),name:r,purpose:`the \`adamantite/lint/${i}\` preset`,scripts:[`check`,`fix`],version:a});return{...o,...s,assess:(e,r)=>t.gen(function*(){let t=yield*s.assess(e,r);if(!t.applicable||n===void 0)return t;let i=yield*n(e,r);return{...t,findings:[...t.findings,...i.findings],warnings:[...t.warnings,...i.warnings]}}),preset:i}}const ei=[`patch`,`--oxlint`,`--typescript`],ti=t.fn(`runEffectTsgoPatch`)(function*(e,t){let n=yield*w.Path,r=yield*j,i=t.quiet?`ignore`:`inherit`,a=yield*ge.String(`PATH`).pipe(ge.withDefault(``)),o=[n.join(e,`node_modules`,`.bin`),a].filter(Boolean).join(he);yield*r.run({args:ei,command:`effect-tsgo`,cwd:e,env:{PATH:o},stderr:i,stdout:i})}),ni=`prepare`,q=`adamantite prepare`;function ri(e){return e?.includes(q)??!1}function ii(e,t){let n=e.scripts?.[ni];return ri(n)?[]:[{currentState:n===void 0?`\`package.json\` has no \`${ni}\` script, so nothing patches Oxlint for the \`effecttsgo\` rules after an install.`:`The \`${ni}\` script (\`${n}\`) does not run \`${q}\`.`,goal:[`Make the \`${ni}\` script in \`package.json\` run \`${q}\`. Put it first, then \`&&\`, then the existing commands in parentheses, such as \`${q} && (husky || true)\`. A command such as \`cd ..\` then cannot move it out of the project directory, and a fallback such as \`|| true\` cannot hide a failed patch.`,`Run \`${q}\` once, so the installed Oxlint, oxlint-tsgolint, and TypeScript binaries are patched.`],id:`missing-effect-tsgo-prepare`,integration:t,notes:["Without the patch, Oxlint stops with `Unknown plugin: 'effecttsgo'`.","Package managers run `prepare` after a bare install, such as `npm install` or `npm ci`, which restores the unpatched binaries. `adamantite init` and `adamantite update` patch after the installs that they run.","A production-only install, such as `npm ci --omit=dev`, also runs `prepare` but does not install Adamantite. Use `--ignore-scripts` for those installs."],title:`Missing adamantite prepare step`}]}const ai=t.fn(`updatePrepareScript`)(function*(e){let t=yield*R(e),n=t.scripts?.[ni]?.trim();if(ri(n))return`present`;let r=n!==void 0&&n!==``;return t.scripts={...t.scripts,[ni]:r?`${q} && (${n})`:q},yield*ct(e,t),r?`merged`:`added`}),J=`tsconfig.json`,oi=`@effect/language-service`,si={diagnostics:!1,name:oi},ci=`${JSON.stringify({compilerOptions:{plugins:[si]}},null,2)}\n`;function li(e){return qe(e)?e.find(e=>L(e)&&e.name===oi):void 0}const ui=t.fn(`assessTsconfigPlugin`)(function*(e,n){if(yield*B(e))return{findings:[],warnings:[`Skipping the root \`${J}\` check for \`${n}\`: in a monorepo, add \`${JSON.stringify(si)}\` to \`compilerOptions.plugins\` in each package's \`${J}\` or in a shared base config.`]};let r=(yield*w.Path).join(e,J),i=yield*P(r),a=i._tag===`None`?void 0:yield*I(i.value,r).pipe(t.map(e=>L(e)&&L(e.compilerOptions)?li(e.compilerOptions.plugins):void 0));return a?.diagnostics===!1?{findings:[],warnings:[]}:{findings:[{currentState:a===void 0?`\`${J}\` does not configure the \`${oi}\` plugin.`:`The \`${oi}\` plugin in \`${J}\` reports its own diagnostics, so \`tsc\` and the editor repeat every Oxlint report.`,goal:[`Add \`${JSON.stringify(si)}\` to \`compilerOptions.plugins\` in \`${J}\`, or set \`diagnostics\` to \`false\` in the existing entry. Keep every other plugin and option.`],id:`missing-effect-language-service-plugin`,integration:n,notes:["The `effecttsgo` rules read their options, such as `allowedUnstableApis`, from this entry."],reference:{content:ci,language:`json`},title:`Effect language service is not configured`}],warnings:[]}}),di=t.fn(`updateTsconfigPlugin`)(function*(e){if(yield*B(e))return`monorepo`;let t=(yield*w.Path).join(e,J),n=yield*P(t);if(n._tag===`None`)return`missing`;let r=yield*I(n.value,t);if(!L(r))return yield*new Me({path:t});let i=r.compilerOptions??{};if(!L(i))return yield*new Me({path:t});let a=i.plugins??[];if(!qe(a))return yield*new Me({path:t});let o=li(a),s=o?a.map(e=>e===o?{...o,diagnostics:!1}:e):[...a,si];return yield*F(t,it(n.value,{...r,compilerOptions:{...i,plugins:s}})),`updated`}),fi=`@effect/tsgo`;var Y=$r({assess:(e,n)=>t.gen(function*(){let t=yield*ui(e,fi);return{findings:[...ii(n,fi),...t.findings],warnings:t.warnings}}),detect:e=>Qr(e,`effect`),name:fi,patch:ti,preset:`effect`,update:e=>t.gen(function*(){return{prepare:yield*ai(e),tsconfig:yield*di(e)}}),version:`0.54.0`}),pi=$r({name:`oxlint-plugin-react-doctor`,preset:`react-doctor`,version:`0.9.18`});const mi=[$r({name:`@shadcn/lint`,preset:`shadcn`,version:`0.2.1`}),pi,Y];var hi=Mt({name:`oxlint-tsgolint`,purpose:`the managed lint scripts`,scripts:[`check`,`fix`],version:`7.0.2004`});const gi=[{path:`tsconfig.json`,type:`config`}],X=`adamantite/typescript`,_i={extends:X},vi=["Skipping `tsconfig.json` setup: a root config in a monorepo makes TypeScript treat all packages as one project.",`To use the TypeScript preset, add \`"extends": "${X}"\` to each package's \`tsconfig.json\` or to a shared base config.`];function yi(e){return x.isString(e)?e===X?e:[e,X]:s.isArray(e)?e.includes(X)?e:[...e,X]:X}var Z=M({assess:(e,n)=>t.gen(function*(){let t=ut(n);if(!t.includes(`check`)&&!t.includes(`fix`))return{applicable:!1,warnings:[]};if(yield*B(e))return{applicable:!0,findings:[],packageActions:[],warnings:vi};let r=(yield*w.Path).join(e,gi[0].path),i=yield*P(r);if(i._tag===`None`)return{applicable:!0,findings:[{currentState:"`tsconfig.json` is missing.",goal:["Create `tsconfig.json` and set `extends` to include `adamantite/typescript`."],id:`missing-tsconfig`,integration:`tsconfig`,reference:{content:`${JSON.stringify(_i,null,2)}\n`,language:`json`},title:`Missing TypeScript configuration`}],packageActions:[],warnings:[]};let a=yield*I(i.value,r);return{applicable:!0,findings:x.isObject(a)&&(a.extends===X||s.isArray(a.extends)&&a.extends.includes(X))?[]:[{currentState:"`tsconfig.json` does not extend `adamantite/typescript`.",goal:["Add `adamantite/typescript` to `extends`. Preserve every existing TypeScript option and existing base config."],id:`missing-adamantite-tsconfig-extends`,integration:`tsconfig`,reference:{content:`${JSON.stringify(_i,null,2)}\n`,language:`json`},title:`TypeScript preset is not configured`}],packageActions:[],warnings:[]}}),config:gi[0].path,create:e=>t.gen(function*(){let t=yield*w.Path;yield*Ke(t.join(e,gi[0].path),_i)}),detect:e=>t.gen(function*(){let t=yield*C.FileSystem,n=yield*w.Path;return yield*t.exists(n.join(e,gi[0].path))}),files:gi,kind:`workspace`,name:`tsconfig`,update:e=>t.gen(function*(){let t=(yield*w.Path).join(e,gi[0].path),n=yield*N(t),r=yield*I(n,t);if(!x.isObject(r))return yield*new Me({path:t});let i=yield*Je(_i,r),a=Object.fromEntries([...Object.entries(i),[`extends`,yi(`extends`in r?r.extends:void 0)]]);yield*F(t,it(n,a))})});const bi=[V,U,W,Zr,...mi,H,hi,Z,pr,K],xi=t.fn(`collectApplicableAssessments`)(function*(e,n,r){return yield*t.forEach(e,e=>e.assess(n,r).pipe(t.map(t=>t.applicable?d.some({assessment:t,name:e.name}):d.none())),{concurrency:`unbounded`}).pipe(t.map(e=>s.getSomes(e)))});function Si(e,t,n){return xi(e,t,n)}const Ci=t.fn(`assessProject`)(function*(e,t){let n=t??(yield*R(e)),r=yield*Si(bi,e,n);return{applicableIntegrations:r.map(({name:e})=>e),findings:r.flatMap(({assessment:e})=>e.findings),packageActions:r.flatMap(({assessment:e})=>e.packageActions),warnings:r.flatMap(({assessment:e})=>e.warnings)}});function wi(e,t){return e.findings.length===0?Ti(e.warnings,t):Ei(e.findings,e.warnings,t)}function Ti(e,t){return[`# Adamantite doctor warnings`,``,`This project uses Adamantite ${t} to manage linting, formatting, and type tooling.`,"`adamantite doctor` found no repair findings, but reported these warnings:",``,...e.map(e=>`- ${e}`),``].join(`
|
|
116
|
+
`)}function Ei(e,t,n){let r=e.map((e,t)=>{let n=e.goal.map(e=>` - ${e}`).join(`
|
|
112
117
|
`),r=e.reference?`\n- **Reference:**\n\n\`\`\`${e.reference.language}\n${e.reference.content.trimEnd()}\n\`\`\``:``,i=e.notes&&e.notes.length>0?`\n- **Notes:**\n${e.notes.map(e=>` - ${e}`).join(`
|
|
113
118
|
`)}`:``;return`## ${t+1}. ${e.title}\n\n- **Current state:** ${e.currentState}\n- **Goal:**\n${n}${r}${i}`}),i=t.length>0?[`## Assessment warnings`,``,`Account for these warnings while fixing the findings:`,``,...t.map(e=>`- ${e}`),``]:[];return[`# Adamantite doctor findings`,``,`This project uses Adamantite ${n} to manage linting, formatting, and type tooling.`,`\`adamantite doctor\` found ${e.length} issue(s). Fix them so that \`adamantite doctor\` exits 0.`,``,...i,r.join(`
|
|
114
119
|
|
|
115
120
|
`),``,`## Verify`,``,"Run `adamantite doctor` — through your package runner, such as `npx` or `pnpm exec`, if it is not on PATH.",`All findings above must be gone and it must exit 0.`,`Do not suppress or work around checks; fix the underlying state.`,``].join(`
|
|
116
|
-
`)}const
|
|
121
|
+
`)}const Di=[{command:`claude`,name:`Claude Code`,seedArguments:e=>[e]},{command:`codex`,name:`Codex`,seedArguments:e=>[e]},{command:`cursor-agent`,name:`Cursor`,seedArguments:e=>[e]},{command:`gemini`,name:`Gemini CLI`,seedArguments:e=>[`-i`,e]},{command:`grok`,name:`Grok Build`,probeArguments:[`version`],seedArguments:e=>[e]},{command:`opencode`,name:`OpenCode`,seedArguments:e=>[`--prompt`,e]}];var Oi=class extends y.TaggedError(`AgentSessionFailed`){};const ki=()=>{},Ai=t.acquireRelease(t.sync(()=>{let e=f.listeners(`SIGINT`);return f.removeAllListeners(`SIGINT`),f.on(`SIGINT`,ki),e}),e=>t.sync(()=>{f.removeAllListeners(`SIGINT`);for(let t of e)f.on(`SIGINT`,t)}));var ji=class e extends g.Service()(`CodingAgents`){static layer=l.effect(this,t.gen(function*(){let n=yield*j,r=(e,r)=>n.exitCode({args:[...e.probeArguments??[`--version`]],command:e.command,cwd:r,stderr:`ignore`,stdout:`ignore`}).pipe(t.timeout(`10 seconds`),t.isSuccess);return e.of({detectInstalled:t.fn(`CodingAgents.detectInstalled`)(e=>t.forEach(Di,t=>r(t,e),{concurrency:`unbounded`}).pipe(t.map(e=>Di.filter((t,n)=>e[n])))),runSession:t.fn(`CodingAgents.runSession`)(function*({agent:e,cwd:t,prompt:r}){yield*Ai,yield*n.exitCode({args:e.seedArguments(r),command:e.command,cwd:t,detached:!1,stderr:`inherit`,stdin:`inherit`,stdout:`inherit`})},t.scoped,t.mapError(e=>new Oi({cause:e,reason:e._tag===`CliNotFound`?`not-found`:`spawn-failed`})))})}))},Mi=class extends g.Service()(`TerminalCapabilities`){static layer=l.succeed(this)({copyToClipboard:e=>t.sync(()=>{let t=Buffer.from(e).toString(`base64`);f.stdout.write(`\u001B]52;c;${t}\u0007`)}),isInteractive:t.sync(()=>f.stdin.isTTY&&f.stdout.isTTY)})},Q=class extends g.Service()(`Prompter`){static layerWithSpinner(e){return l.succeed(this)({cancel:e=>t.sync(()=>{O.cancel(e)}),confirm:e=>t.promise(()=>O.confirm(e)).pipe(t.filterOrFail(e=>!O.isCancel(e),()=>new Le({}))),intro:e=>t.sync(()=>{O.intro(e)}),log:{error:e=>t.sync(()=>{O.log.error(e)}),info:e=>t.sync(()=>{O.log.info(e)}),success:e=>t.sync(()=>{O.log.success(e)}),warning:e=>t.sync(()=>{O.log.warning(e)})},message:e=>t.sync(()=>{O.log.message(e,{spacing:0,withGuide:!1})}),multiselect:e=>t.promise(()=>O.multiselect(e)).pipe(t.filterOrFail(e=>!O.isCancel(e),()=>new Le({}))),note:(e,n)=>t.sync(()=>{O.note(e,n)}),outro:e=>t.sync(()=>{O.outro(e)}),select:e=>t.promise(()=>O.select(e)).pipe(t.filterOrFail(e=>!O.isCancel(e),()=>new Le({}))),withSpinner:(r,i)=>t.acquireUseRelease(t.sync(()=>{let t=e();return t.start(i.start),t}),e=>r({message:n=>t.sync(()=>{e.message(n)})}),(e,r)=>t.sync(()=>{e.stop(n.match(r,{onFailure:()=>i.failure,onSuccess:e=>x.isFunction(i.success)?i.success(e):i.success}))}))})}static layer=this.layerWithSpinner(O.spinner)};function Ni(e){let t=[`Current state\n${e.currentState}`,`Goal\n${e.goal.map(e=>`• ${e}`).join(`
|
|
117
122
|
`)}`];return e.reference&&t.push(`Reference\n${e.reference.content.trimEnd()}`),e.notes&&e.notes.length>0&&t.push(`Notes\n${e.notes.map(e=>`• ${e}`).join(`
|
|
118
123
|
`)}`),t.join(`
|
|
119
124
|
|
|
120
|
-
`)}const
|
|
121
|
-
`).reduce((e,t)=>Math.max(e,t.trim().length),0);!e||e<t||(yield*h.info(
|
|
122
|
-
`);return[
|
|
123
|
-
`)}const
|
|
125
|
+
`)}const Pi=t.fn(`printFindings`)(function*(e){let t=yield*Q;for(let[n,r]of e.entries())yield*t.note(Ni(r),`${n+1}. ${r.title}`)}),Fi=`0.44.0`;var Ii=c.make(`doctor`).pipe(c.withDescription(`Assess Adamantite-managed integrations in the current project`),c.withHandler(()=>t.gen(function*(){let e=f.cwd(),n=yield*ji,i=yield*Q,a=yield*Mi,o=yield*a.isInteractive;o&&(yield*i.intro(`💠 adamantite doctor`));let s=t.gen(function*(){return yield*i.outro(`⚠️ Doctor found issues.`),yield*new Se({command:`doctor`,exitCode:r.ExitCode(1)})}),c=yield*R(e);if(!c.devDependencies?.adamantite&&!c.dependencies?.adamantite){let e="`adamantite` is not installed in this project. Install it before running `adamantite doctor`.";return o?(yield*i.log.warning(e),yield*i.outro(`⚠️ Doctor found issues.`)):yield*i.message(e),yield*new Se({command:`doctor`,exitCode:r.ExitCode(1)})}let l=yield*Ci(e);if(o)for(let e of l.warnings)yield*i.log.warning(e);if(l.applicableIntegrations.length===0){o&&(yield*i.log.success(`No applicable integrations found.`),yield*i.outro(`✅ Doctor completed successfully!`));return}if(l.findings.length===0){o?(yield*i.log.success(`No issues found.`),yield*i.outro(`✅ Doctor completed successfully!`)):l.warnings.length>0&&(yield*i.message(wi(l,Fi)));return}if(!o)return yield*i.message(wi(l,Fi)),yield*new Se({command:`doctor`,exitCode:r.ExitCode(1)});let u=e=>t.gen(function*(){(yield*i.confirm({initialValue:!0,message:`Copy the Markdown prompt for a coding agent?`}))&&(yield*i.message(e),yield*a.copyToClipboard(e),yield*i.log.success(`The Markdown prompt was printed and sent to the terminal clipboard.`))});yield*Pi(l.findings);let d=yield*i.withSpinner(()=>n.detectInstalled(e),{start:`Checking for installed coding agents...`,success:e=>e.length===0?`No supported coding agent CLI was found on PATH.`:`Found ${e.map(e=>e.name).join(`, `)}.`});d.length===0&&(yield*i.log.info(`Doctor can hand findings off when one of these CLIs is installed: ${Di.map(e=>`\`${e.command}\``).join(`, `)}.`));let p=wi(l,Fi),m=yield*i.select({message:`How do you want to resolve these findings?`,options:[...d.map(e=>({label:`Hand off to ${e.name}`,value:e})),{label:`Copy the Markdown prompt for a coding agent`,value:`copy`},{label:`Do nothing`,value:`done`}]});if(m===`done`)return yield*s;if(m===`copy`)return yield*i.message(p),yield*a.copyToClipboard(p),yield*i.log.success(`The Markdown prompt was printed and sent to the terminal clipboard.`),yield*s;let h=m;if(yield*i.log.info(`Handing the terminal to ${h.name}. Exit the agent to return to Doctor.`),!(yield*n.runSession({agent:h,cwd:e,prompt:p}).pipe(t.as(!0),t.catchTag(`AgentSessionFailed`,e=>i.log.error(e.reason===`not-found`?`\`${h.command}\` was not found on PATH. Install ${h.name} or copy the prompt instead.`:`Failed to start ${h.name}: ${e.cause.message}`).pipe(t.as(!1))))))return yield*u(p),yield*s;let g=yield*Ci(e);if(g.findings.length===0)yield*i.log.success(`All findings were resolved by ${h.name}.`),yield*i.outro(`✅ Doctor completed successfully!`);else return yield*i.log.warning(`${g.findings.length} of ${l.findings.length} findings remain after the ${h.name} session.`),yield*Pi(g.findings),yield*u(wi(g,Fi)),yield*s}).pipe(t.catchTag(`OperationCancelled`,()=>t.gen(function*(){return yield*(yield*Q).cancel(`Doctor was cancelled. The findings remain.`),yield*new Se({command:`doctor`,exitCode:r.ExitCode(1)})})))));const Li=T.File(`files`,{mustExist:!0}).pipe(T.withDescription(`Specific files to fix (optional)`),T.variadic()),Ri=u.Boolean(`suggested`).pipe(u.withDefault(!1),u.withDescription(`Apply suggested fixes`)),zi=u.Boolean(`dangerous`).pipe(u.withDefault(!1),u.withDescription(`Apply dangerous fixes`)),Bi=u.Boolean(`all`).pipe(u.withDefault(!1),u.withDescription(`Apply all fixes, including suggested and dangerous fixes`)),Vi=u.Literals(`only`,[`format`,`lint`]).pipe(u.optional,u.withDescription("Run one stage: `format` (oxfmt) or `lint` (oxlint). Arguments after `--` go to that stage"));var Hi=c.make(`fix`,{all:Bi,dangerous:zi,files:Li,only:Vi,suggested:Ri}).pipe(c.withDescription(`Fix lint and formatting issues in code`),c.withHandler(({all:e,dangerous:n,files:r,only:i,suggested:a})=>t.gen(function*(){let t=yield*Ue,o=yield*j,c=d.getOrUndefined(i);if(c===`format`&&(e||n||a))return yield*new Pe({reason:"`--suggested`, `--dangerous`, and `--all` apply to the lint stage. Remove them or `--only format`."});let l=s.dedupe(r),u=c??`lint`,f=[{args:s.dedupe([`--fix`,...a||e?[`--fix-suggestions`]:[],...n||e?[`--fix-dangerously`]:[],...l]),command:W.name,name:`lint`,title:`🔧 Fixing lint issues`},{args:[`--write`,...l],command:U.name,name:`format`,title:`✨ Formatting`}];yield*o.runAll(f.filter(e=>c===void 0||e.name===c).map(e=>({args:[...e.args,...e.name===u?t:[]],command:e.command,title:e.title})))})));const Ui=' .o8 . o8o . \n "888 .o8 `"\' .o8 \n .oooo. .oooo888 .oooo. ooo. .oo. .oo. .oooo. ooo. .oo. .o888oo oooo .o888oo .ooooo. \n`P )88b d88\' `888 `P )88b `888P"Y88bP"Y88b `P )88b `888P"Y88b 888 `888 888 d88\' `88b \n .oP"888 888 888 .oP"888 888 888 888 .oP"888 888 888 888 888 888 888ooo888 \nd8( 888 888 888 d8( 888 888 888 888 d8( 888 888 888 888 . 888 888 . 888 .o \n`Y888""8o `Y8bod88P" `Y888""8o o888o o888o o888o `Y888""8o o888o o888o "888" o888o "888" `Y8bod8P\' \n \n \n ',Wi=t.gen(function*(){let e=yield*(yield*_e.Terminal).columns,t=Ui.split(`
|
|
126
|
+
`).reduce((e,t)=>Math.max(e,t.trim().length),0);!e||e<t||(yield*h.info(Ui))}),Gi=[`check`,`fix`,`analyze`],Ki=[`vscode`,`zed`],qi=t.fn(`validateInitOptions`)(function*(e,t){let n={agents:e.agents,editors:s.dedupe(e.editors),githubActions:e.githubActions,installExtensions:e.installExtensions,overwriteScripts:e.overwriteScripts,presets:s.dedupe(e.presets),scripts:s.dedupe(e.scripts),typescript:e.typescript};if(n.scripts.length===0)return yield*new A({reason:"Select at least one script with `--script <name>`."});let r=n.scripts.includes(`check`)||n.scripts.includes(`fix`);return n.presets.length>0&&!r?yield*new A({reason:"`--preset` requires the `check` or `fix` script."}):n.presets.includes(`react-doctor`)&&!n.presets.includes(`react`)?yield*new A({reason:"`--preset react-doctor` requires `--preset react`."}):n.typescript&&!r?yield*new A({reason:"`--typescript` requires the `check` or `fix` script."}):n.installExtensions&&n.editors.length===0?yield*new A({reason:"`--install-extensions` requires at least one `--editor`."}):n.githubActions&&!zn(n.scripts)?yield*new A({reason:"`--github-actions` requires a CI-compatible script."}):n.githubActions&&t.nonInteractive&&!lt(t.packageManager)?yield*new A({reason:`\`--github-actions\` does not support the detected package manager \`${t.packageManager}\`. Use bun, deno, npm, pnpm, or yarn.`}):n}),Ji=u.Boolean(`non-interactive`).pipe(u.withDefault(!1),u.withDescription(`Configure without prompts; requires at least one --script`)),Yi=u.Literals(`script`,Gi).pipe(u.atMost(Gi.length),u.withDescription(`Package script to configure; repeatable and required in non-interactive mode`)),Xi=u.Literals(`preset`,Rt).pipe(u.atMost(Rt.length),u.withDescription(`Oxlint preset to configure; repeatable and requires --script check or fix`)),Zi=u.Literals(`editor`,Ki).pipe(u.atMost(Ki.length),u.withDescription(`Editor to configure; may be specified multiple times`)),Qi=u.Boolean(`typescript`).pipe(u.withDefault(!1),u.withDescription(`Configure the TypeScript preset; requires --script check or fix`)),$i=u.Boolean(`install-extensions`).pipe(u.withDefault(!1),u.withDescription(`Install recommended extensions; requires at least one --editor`)),ea=u.Boolean(`github-actions`).pipe(u.withDefault(!1),u.withDescription(`Configure CI; requires a compatible script and bun, deno, npm, pnpm, or yarn`)),ta={agents:u.Boolean(`agents`).pipe(u.withDefault(!1),u.withDescription(`Add Adamantite guidance to AGENTS.md`)),editors:Zi,githubActions:ea,installExtensions:$i,nonInteractive:Ji,overwriteScripts:u.Boolean(`overwrite-scripts`).pipe(u.withDefault(!1),u.withDescription(`Replace existing package scripts that conflict with Adamantite's managed commands`)),presets:Xi,scripts:Yi,typescript:Qi},na=e=>`\`${e.script}\` is currently \`${e.command}\`; Adamantite would replace it with \`${z[e.script]}\`.`,ra=t.fn(`collectInteractiveInitOptions`)(function*(e,t){let n=yield*Q,r=yield*n.multiselect({message:"Which scripts do you want to add to your `package.json`?",options:[{hint:`recommended`,label:`check - check formatting, lint issues, and type errors`,value:`check`},{hint:`recommended`,label:`fix - apply safe lint fixes and format code`,value:`fix`},{label:t?`analyze - check monorepo consistency using Sherif and find unused dependencies, exports, and files using knip`:`analyze - find unused dependencies, exports, and files using knip`,value:`analyze`}]}),i=dt(yield*R(e),r),a=!1;if(i.length>0){for(let e of i)yield*n.log.warning(na(e));a=yield*n.confirm({initialValue:!1,message:i.length===1?`Overwrite this existing script with Adamantite's command?`:`Overwrite these existing scripts with Adamantite's commands?`})}let o=r.includes(`check`)||r.includes(`fix`),s=[];o&&(s=yield*n.multiselect({message:`Which presets do you want to install? (core is always included)`,options:[{hint:`React correctness, JSX accessibility, and render performance rules`,label:`react`,value:`react`},{hint:`Strict React feature code: no state, effect, or memoization hooks outside hook modules`,label:`react-strict`,value:`react-strict`},{hint:`React state and effect misuse, such as effects used as event handlers and fetches in effects; requires react`,label:`react-doctor`,value:`react-doctor`},{hint:`TanStack Query: queries defined once with queryOptions() so route loaders can preload them, no query data copied into state`,label:`tanstack`,value:`tanstack`},{hint:`Next.js pitfalls around scripts, fonts, images, and document/head usage`,label:`next.js`,value:`nextjs`},{hint:`Vue 3 correctness rules and deprecated API detection`,label:`vue`,value:`vue`},{hint:`Effect misuse, such as effects that never run and unhandled errors; installs @effect/tsgo and patches Oxlint and TypeScript`,label:`effect`,value:`effect`},{hint:`Jest test hygiene: focused/disabled tests, matcher and snapshot discipline`,label:`jest`,value:`jest`},{hint:`Vitest test hygiene: focused/disabled tests, matcher and snapshot discipline`,label:`vitest`,value:`vitest`},{hint:`Node.js callback and CommonJS pitfalls`,label:`node`,value:`node`},{hint:`Framework-neutral strictness: no deep or wide destructuring, no type assertions outside tests`,label:`strict`,value:`strict`},{hint:`Rejects low-signal escape hatches: unjustified assertions, unknown leaks, module mocks`,label:`antislop`,value:`antislop`},{hint:`Tailwind v4 design system: no restyled components, raw colors, arbitrary values, or unknown classes`,label:`shadcn`,value:`shadcn`}],required:!1}),s.includes(`react-doctor`)&&!s.includes(`react`)&&(s=[`react`,...s],yield*n.log.info("Added the `react` preset, which `react-doctor` requires.")));let c=o?yield*n.confirm({initialValue:!0,message:t?"Adamantite provides a TypeScript preset to enforce strict type-safety. In a monorepo, each package's `tsconfig.json` must extend it. Would you like instructions on how to set it up?":`Adamantite provides a TypeScript preset to enforce strict type-safety. Would you like to use it?`}):!1,l=yield*n.multiselect({message:`Which editors do you want to configure? (optional)`,options:[{label:`VSCode / Cursor / Windsurf`,value:`vscode`},{label:`Zed`,value:`zed`}],required:!1}),u=l.length>0?yield*n.confirm({initialValue:!0,message:`Do you want to install the recommended editor extensions?`}):!1,d=zn(r)?yield*n.confirm({message:`Do you want to add a GitHub Actions workflow to run checks in CI?`}):!1;return{agents:yield*n.confirm({initialValue:!0,message:`Add Adamantite guidance to AGENTS.md so coding agents know how to run project checks?`}),editors:l,githubActions:d,installExtensions:u,overwriteScripts:a,presets:s,scripts:r,typescript:c}}),ia=[{path:`.vscode/settings.json`,type:`config`}],aa={"[css]":{"editor.defaultFormatter":`oxc.oxc-vscode`},"[graphql]":{"editor.defaultFormatter":`oxc.oxc-vscode`},"[javascript]":{"editor.defaultFormatter":`oxc.oxc-vscode`},"[javascriptreact]":{"editor.defaultFormatter":`oxc.oxc-vscode`},"[json]":{"editor.defaultFormatter":`oxc.oxc-vscode`},"[jsonc]":{"editor.defaultFormatter":`oxc.oxc-vscode`},"[typescript]":{"editor.defaultFormatter":`oxc.oxc-vscode`},"[typescriptreact]":{"editor.defaultFormatter":`oxc.oxc-vscode`},"editor.codeActionsOnSave":{"source.fixAll.oxc":`explicit`},"editor.defaultFormatter":`oxc.oxc-vscode`,"editor.formatOnPaste":!0,"editor.formatOnSave":!0,"oxc.typeAware":!0};var $=M({config:ia[0].path,create:e=>t.gen(function*(){let t=yield*w.Path,n=t.join(e,ia[0].path);yield*We(t.dirname(n)),yield*Ke(n,aa)}),detect:e=>t.gen(function*(){let t=yield*C.FileSystem,n=yield*w.Path;return yield*t.exists(n.join(e,ia[0].path))}),extension:(e=[])=>t.gen(function*(){let n=[];(e.includes(`check`)||e.includes(`fix`))&&n.push(`oxc.oxc-vscode`),e.includes(`analyze`)&&n.push(`webpro.vscode-knip`);for(let e of n)yield*(yield*j).run({args:[`--install-extension`,e],command:`code`}).pipe(t.mapError(t=>t._tag===`CliNotFound`&&t.command===`code`?new ze({cause:t}):new Ee({cause:t._tag===`CommandFailed`?t.exitCode:t,extension:e})))}),files:ia,kind:`editor`,name:`vscode`,update:e=>t.gen(function*(){let t=(yield*w.Path).join(e,ia[0].path),n=yield*N(t),r=yield*I(n,t);if(!x.isObject(r))return yield*new Me({path:t});let i=yield*Je(aa,r);yield*F(t,it(n,i))})});const oa=`<!-- ADAMANTITE:START -->`,sa=`<!-- ADAMANTITE:END -->`;function ca(e,t,n){let r=me(e,t),i=z[t];switch(t){case`analyze`:return`- Run \`${r}\` after changing dependencies, imports, or exports.${n?` It also checks monorepo package consistency.`:``} Direct command: \`${i}\`.`;case`check`:return`- Run \`${r}\` to catch formatting, lint, and type issues. Direct command: \`${i}\`.`;case`fix`:return`- Run \`${r}\` to apply safe lint fixes and format code. Direct command: \`${i}\`.`}}function la({isMonorepo:e,packageManager:t,scripts:n}){let r=[`check`,`fix`,`analyze`].filter(e=>n.includes(e)).map(n=>ca(t,n,e)),i=[`## Adamantite`,``,`This project uses Adamantite for its managed formatting, linting, type checking, and dependency-analysis setup.`,``,...r.length>0?[`- Prefer the package scripts Adamantite added for this workspace.`,...r]:[],...n.includes(`check`)||n.includes(`fix`)?["- Write project-specific lint rules in `.adamantite/rules/`, one rule for each file. Run `adamantite rule add <name>` to start a rule with its authoring guidance."]:[],"- Run `adamantite doctor` and follow its findings to repair managed setup."].join(`
|
|
127
|
+
`);return[oa,``,i,``,sa,``].join(`
|
|
128
|
+
`)}const ua=(e,n)=>t.gen(function*(){let t=(yield*w.Path).join(e,`AGENTS.md`),r=b(yield*P(t),d.getOrElse(()=>``)),i=b(r,S.indexOf(oa)),a=b(r,S.indexOf(sa)),o=b(d.all({end:a,start:i}),d.filter(({end:e,start:t})=>t<e)),s=la(n);if(d.isSome(o)){let{end:e,start:n}=o.value,i=e+23,a=`${r.slice(0,n)}${s.trimEnd()}${r.slice(i)}`;return yield*F(t,a.endsWith(`
|
|
124
129
|
`)?a:`${a}\n`),`updated`}if(d.isSome(i)||d.isSome(a))return`malformed`;let c=r.length===0||r.endsWith(`
|
|
125
130
|
|
|
126
131
|
`)?``:r.endsWith(`
|
|
127
132
|
`)?`
|
|
128
133
|
`:`
|
|
129
134
|
|
|
130
|
-
`;return yield*P(t,`${r}${c}${s}`),`updated`}),Yi=(e,n)=>t.gen(function*(){yield*(yield*Q).withSpinner(()=>En(e,n),{failure:`Failed to install dependencies.`,start:`Installing dependencies...`,success:`Dependencies installed.`})});function Xi(e,n,r){return t.gen(function*(){let i=yield*Q,a=yield*i.withSpinner(a=>t.gen(function*(){let t=yield*n.detect(e);for(let e of t.warnings)yield*i.log.warning(e);return t.active===null?(yield*a.message(`\`${n.config}\` not found, creating...`),yield*r,{created:!0,legacyConfig:null}):t.active.format===`ts`?(yield*a.message(`Found \`${n.config}\`, keeping existing config.`),{created:!1,legacyConfig:null}):(yield*a.message(`Found \`${t.active.file}\`, keeping existing config.`),{created:!1,legacyConfig:t.active.file})}),{failure:`Failed to set up ${n.name} config.`,start:`Setting up ${n.name} config...`,success:e=>e.created?`${n.name} config created successfully.`:`${n.name} config is ready.`});a.legacyConfig&&(yield*i.log.info(`Legacy \`${a.legacyConfig}\` was preserved during \`adamantite init\`. Run \`adamantite doctor\` and follow its findings to migrate it to the latest ${n.name} config.`))})}const Zi=(e,n,r)=>t.gen(function*(){let i=yield*Q,a=yield*R(e),o=r.overwriteScripts?[]:Ye(a,n),s=new Set(o.map(e=>e.script)),c=n.filter(e=>!s.has(e));yield*i.withSpinner(()=>t.gen(function*(){if(c.length!==0){a.scripts??={};for(let e of c)a.scripts[e]=z[e];yield*Ke(e,a)}}),{failure:"Failed to add scripts to `package.json`.",start:"Adding scripts to your `package.json`...",success:o.length===0?"Scripts added to your `package.json`":c.length===0?"Kept your existing `package.json` scripts.":"Scripts added to your `package.json`; conflicting scripts were kept."});let l=r.nonInteractive?"Use `--overwrite-scripts` to replace it.":"Re-run `adamantite init` and confirm overwriting to replace it.";for(let e of o)yield*i.log.warning(`Kept existing \`${e.script}\` script (\`${e.command}\`) instead of \`${z[e.script]}\`. ${l}`);return o.length>0&&(yield*i.log.info("Adamantite commands forward extra arguments after `--`, so custom flags can be kept, e.g. `adamantite analyze -- --directory packages/app`.")),c}),Qi=(e,n)=>t.gen(function*(){let r=yield*Q;if(n){yield*y(ni,t.forEach(e=>r.log.info(e)));return}yield*r.withSpinner(n=>t.gen(function*(){return(yield*Z.detect(e))?(yield*n.message(`\`${Z.config}\` found, updating...`),yield*Z.update(e),!1):(yield*n.message(`\`${Z.config}\` not found, creating...`),yield*Z.create(e),!0)}),{failure:`Failed to set up TypeScript config.`,start:`Setting up TypeScript config...`,success:e=>e?`\`${Z.config}\` created successfully`:`\`${Z.config}\` updated successfully`})}),$i=e=>t.gen(function*(){let t=yield*Q,n=yield*Y.update(e);n.prepare===`merged`&&(yield*t.log.info("Added `adamantite prepare` to the start of your existing `prepare` script.")),n.tsconfig===`monorepo`&&(yield*t.log.info("In a monorepo, add the Effect language service entry to each package's `tsconfig.json` or to a shared base config. Run `adamantite doctor` for the reference entry.")),n.tsconfig===`missing`&&(yield*t.log.warning("No `tsconfig.json` found, so the Effect language service is not configured. Run `adamantite doctor` for the reference entry."))}),ea=e=>t.gen(function*(){let n=yield*Q;(yield*Y.detect(e))&&(yield*n.withSpinner(()=>Y.patch(e,{quiet:!0}),{failure:`Failed to patch Oxlint and TypeScript.`,start:`Patching Oxlint and TypeScript with @effect/tsgo...`,success:`Oxlint and TypeScript patched with @effect/tsgo.`}).pipe(t.catchTag([`CommandFailed`,`CliNotFound`,`PlatformError`],()=>n.log.warning("Run `adamantite prepare` to see why the patch failed. Oxlint cannot load the `effect` preset until it succeeds."))))}),ta=(e,n)=>t.gen(function*(){let r=yield*Q;n.includes(`vscode`)&&(yield*r.withSpinner(n=>t.gen(function*(){let t=yield*$.detect(e);return yield*n.message(`\`${$.config}\` ${t?`found, updating`:`not found, creating`}...`),yield*t?$.update(e):$.create(e),!t}),{failure:`Failed to set up VS Code config.`,start:`Checking for \`${$.config}\`...`,success:e=>`\`${$.config}\` ${e?`created`:`updated`} with Adamantite preset.`})),n.includes(`zed`)&&(yield*r.withSpinner(n=>t.gen(function*(){let t=yield*K.detect(e);return yield*n.message(`\`${K.config}\` ${t?`found, updating`:`not found, creating`}...`),yield*t?K.update(e):K.create(e),!t}),{failure:`Failed to set up Zed config.`,start:`Checking for \`${K.config}\`...`,success:e=>`\`${K.config}\` ${e?`created`:`updated`} with Adamantite preset.`}))}),na=(e,n)=>t.gen(function*(){let r=yield*Q,i=e.includes(`zed`),a=e.includes(`vscode`);yield*r.withSpinner(e=>t.gen(function*(){return a&&(yield*e.message(`Installing VS Code extension...`),yield*$.extension(n)),!0}),{start:`Installing editor extensions...`,success:i&&!a?`Zed extensions require manual install.`:`Editor extensions installed successfully.`}).pipe(t.catchTags({FailedToInstallExtension:e=>t.gen(function*(){return yield*r.log.warning(`⚠️ ${e.message}`),yield*r.log.warning(`Please install it manually after setup completes.`),!1}),VscodeCliNotFound:()=>t.gen(function*(){return yield*r.log.error(`VSCode CLI ('code' command) not found.`),yield*r.log.info(`To install it:`),yield*r.log.info(` 1. Open VS Code`),yield*r.log.info(` 2. Press Cmd+Shift+P (macOS) or Ctrl+Shift+P (Windows/Linux)`),yield*r.log.info(` 3. Run 'Shell Command: Install "code" command in PATH'`),!1})})),i&&(yield*r.log.info("Install the Zed `oxc` extension: zed://extension/oxc"))}),ra=(e,n,r)=>t.gen(function*(){let i=yield*Q,a=Zn.files[0].path;yield*i.withSpinner(i=>t.gen(function*(){let t=yield*Zn.detect(e);return yield*i.message(t?`\`${a}\` found, updating...`:`Creating \`${a}\`...`),yield*t?Zn.update(e,{packageManager:n,scripts:r}):Zn.create(e,{packageManager:n,scripts:r}),!t}),{failure:`Failed to set up GitHub Actions workflow.`,start:`Setting up GitHub Actions workflow...`,success:e=>`GitHub Actions workflow ${e?`created`:`updated`} successfully.`})}).pipe(t.catchTag([`FailedToCreateDirectory`,`FailedToParseFile`,`FailedToReadFile`,`FailedToWriteFile`,`PlatformError`],e=>t.gen(function*(){let t=yield*Q;yield*t.log.warning(`Could not set up the GitHub Actions workflow. ${e.message}`),yield*t.log.warning("Fix the reported problem and run `adamantite init` again, or create the workflow manually.")}))),ia=(e,n,r,i)=>t.gen(function*(){let a=yield*Q,o=yield*a.withSpinner(()=>Ji(e,{isMonorepo:i,packageManager:n,scripts:r}),{failure:`Failed to update AGENTS.md.`,start:`Updating AGENTS.md...`,success:`AGENTS.md check complete.`}).pipe(t.catchTag([`FailedToReadFile`,`FailedToWriteFile`],e=>t.gen(function*(){return yield*a.log.warning(`Could not update AGENTS.md. ${e.message} Adamantite will continue initialization.`),`failed`})));o!==`failed`&&o===`malformed`&&(yield*a.log.warning(`Could not update AGENTS.md because Adamantite markers are incomplete. Remove the stale ADAMANTITE marker and run adamantite init again.`))});var aa=c.make(`init`,zi).pipe(c.withDescription(`Initialize Adamantite in the current directory. Setup flags require --non-interactive; omitted boolean setup flags are disabled`),c.withExamples([{command:`adamantite init --non-interactive --script check`,description:`Configure linting without prompts`},{command:`adamantite init --non-interactive --script check --preset react --editor vscode --typescript --install-extensions --github-actions --agents`,description:`Configure a React project with VS Code, TypeScript, CI, and agent guidance`},{command:`adamantite init --non-interactive --script analyze`,description:`Configure analysis; in a detected monorepo it includes Sherif`}]),c.withHandler(e=>t.gen(function*(){let t=f.cwd(),n=yield*Q;yield*Oi,yield*n.intro(`💠 adamantite init`);let r=yield*(yield*wn).detectPackageManager(t);if(!r)return yield*new je({});if(r.warnings?.length)for(let e of r.warnings)yield*n.log.warning(e);yield*n.log.info(`Detected package manager: ${r.name}`);let i=yield*B(t);if(i&&(yield*n.log.info(`We've detected a monorepo setup in your project.`)),!e.nonInteractive&&s.some([e.scripts.length>0,e.presets.length>0,e.editors.length>0,e.typescript,e.installExtensions,e.githubActions,e.agents,e.overwriteScripts],b.isTruthy))return yield*new k({reason:"Setup flags require `--non-interactive`."});let a=e.nonInteractive?e:yield*Vi(t,i),o=yield*ji(a,{nonInteractive:e.nonInteractive,packageManager:r.name}),c=o.scripts,l=o.presets,u=o.editors,d=o.typescript,p=o.installExtensions,m=o.githubActions,h=o.agents,g=c.includes(`check`)||c.includes(`fix`),ee=c.includes(`analyze`),_=ee&&i,v=[`adamantite`];g&&v.push(`${W.name}@${W.version}`,`${$r.name}@${$r.version}`,`${U.name}@${U.version}`,...Qr.filter(e=>l.includes(e.preset)).map(e=>`${e.name}@${e.version}`)),_&&v.push(`${H.name}@${H.version}`),ee&&v.push(`${V.name}@${V.version}`),yield*Yi(t,v),g&&(yield*Xi(t,U,U.create(t)),yield*Xi(t,W,W.create(t,l))),ee&&(yield*Xi(t,V,V.create(t)));let y=yield*Zi(t,c,{nonInteractive:e.nonInteractive,overwriteScripts:o.overwriteScripts});if(h&&(yield*ia(t,r.name,y,i)),d&&(yield*Qi(t,i)),l.includes(`effect`)&&(yield*$i(t)),g&&(yield*ea(t)),yield*ta(t,u),p&&(yield*na(u,c)),m){let e=r.name;qe(e)?yield*ra(t,e,c):yield*n.log.warning(`Skipping GitHub Actions setup: \`${e}\` is not a supported package manager for CI workflow generation.`)}yield*n.log.success(`Your project is now configured`),yield*n.outro(`💠 Adamantite initialized successfully!`)}).pipe(t.catchTags({OperationCancelled:()=>t.gen(function*(){yield*(yield*Q).cancel(`You've cancelled the initialization process.`)})})))),oa=c.make(`prepare`).pipe(c.withDescription("Patch Oxlint and TypeScript for the effect preset. The `prepare` script runs it after each install"),c.withHandler(()=>t.gen(function*(){let e=f.cwd();(yield*Y.detect(e))&&(yield*Y.patch(e,{quiet:!1}))})));const sa=w.File(`file`,{mustExist:!0}).pipe(w.withDescription(`The JavaScript or TypeScript file to parse`)),ca=c.make(`ast`,{file:sa}).pipe(c.withDescription(`Print the ESTree-shaped AST that Oxlint rules visit, to find node names for a custom rule`),c.withHandler(({file:e})=>t.gen(function*(){let t=yield*Q,n=yield*M(e),r=oe(e,n,{preserveParens:!1});if(r.errors.length>0)return yield*new we({errors:r.errors.map(e=>e.message),path:e});yield*t.message(JSON.stringify(r.program,null,2))}))),la=w.String(`name`).pipe(w.withDescription(`The rule name in kebab-case, such as no-process-env`)),ua=u.String(`dir`).pipe(u.optional,u.withDescription(`The rules folder, relative to the current directory. Default: ${yr}. Pass the folder that \`custom({ dir })\` loads, such as a rules folder in a monorepo tooling package`)),da=c.make(`add`,{dir:ua,name:la}).pipe(c.withDescription(`Write a custom rule stub, and the authoring guidance when the rules folder has none`),c.withHandler(({dir:e,name:n})=>t.gen(function*(){let t=yield*Q,r=yield*C.Path,i=f.cwd(),a=yield*Sr(i,n,d.getOrUndefined(e));yield*t.log.success(`Wrote ${r.relative(i,a.rulePath)}.`),a.agentsPath!==void 0&&(yield*t.log.success(`Wrote ${r.relative(i,a.agentsPath)}.`)),yield*t.log.info("`custom()` from `adamantite/lint/custom` loads the rule. Run `adamantite doctor` to check the wiring.")})));var fa=c.make(`rule`).pipe(c.withDescription(`Write and inspect custom Oxlint rules`),c.withSubcommands([da,ca]));const pa=[W,$r,U,H,V];function ma(e,t){return s.filterMap(pa,n=>{if(t.has(n.name))return _.failVoid;let r=e.devDependencies?.[n.name]??e.dependencies?.[n.name];return r&&Ge(r)!==n.version?_.succeed({currentVersion:r,name:n.name,targetVersion:n.version}):_.failVoid})}var ha=c.make(`update`).pipe(c.withDescription(`Update Adamantite-managed dependencies and report setup findings`),c.withHandler(()=>t.gen(function*(){let e=f.cwd(),t=yield*Q;yield*t.intro(`💠 adamantite update`);let n=yield*R(e),r=yield*si(e,n),i=r.packageActions,a=new Set(i.map(e=>e.package)),o=[...i.map(e=>({currentVersion:e.type===`install_package`?`not installed`:e.currentVersion,name:e.package,targetVersion:e.targetVersion})),...ma(n,a)];if(o.length>0){yield*t.log.info(`The following dependencies will be updated:`);for(let e of o)yield*t.log.info(` ${e.name}: ${e.currentVersion} → ${e.targetVersion}`);yield*t.withSpinner(()=>En(e,o.map(e=>`${e.name}@${e.targetVersion}`)),{failure:`Failed to update dependencies`,start:`Updating dependencies...`,success:`Dependencies updated successfully`}),yield*t.log.success(`Dependencies updated successfully.`),(yield*Y.detect(e))&&(yield*t.withSpinner(()=>Y.patch(e,{quiet:!0}),{failure:"Failed to patch Oxlint and TypeScript. Run `adamantite prepare` to see why.",start:`Patching Oxlint and TypeScript with @effect/tsgo...`,success:`Oxlint and TypeScript patched with @effect/tsgo.`}))}let s=o.length===0?r:yield*si(e);for(let e of s.warnings)yield*t.log.warning(e);let c=s.findings;return c.length>0&&(yield*vi(c),yield*t.log.info("Run `adamantite doctor` to get the combined Markdown repair prompt.")),o.length===0&&c.length===0?(yield*t.log.success(`No changes needed.`),`no-changes`):`success`}).pipe(t.tapError(()=>t.gen(function*(){yield*(yield*Q).outro(`❌ Update failed`)})),t.tap(e=>t.gen(function*(){yield*(yield*Q).outro(e===`no-changes`?`✅ Adamantite is already up to date.`:`✅ Update completed successfully!`)})))));const ga=[ln,bn,Ei],_a=[ln,bn,bi,Ei,aa,oa,fa,ha],va=new Set(_a.map(e=>e.name)),ya=new Set(ga.map(e=>e.name)),ba=c.make(`adamantite`).pipe(c.withDescription(`Opinionated preset package for modern TypeScript applications`),c.withSubcommands(_a)),xa=e=>l.mergeAll(o.layer,In.layer.pipe(l.provide(o.layer)),Q.layer,hi.layer.pipe(l.provideMerge(e),l.provide(o.layer)),wn.layer,gi.layer),Sa=t.fn(`runCli`)(function*(e,n){let[r,i]=s.splitWhere(e,e=>e===`--`),a=s.drop(i,1),o=r.find(e=>va.has(e));if(a.length>0&&o!==void 0&&!ya.has(o))return yield*new Ne({command:o});yield*c.runWith(ba,{version:n})(r).pipe(t.provideService(Re,a))}),Ca=t.gen(function*(){let e=yield*(yield*a.Stdio).args;yield*Sa(e,`0.43.0`)}).pipe(t.as(0),t.catchTag(`CommandFailed`,e=>t.succeed(e.exitCode)),t.catch(e=>t.service(Q).pipe(t.flatMap(t=>t.log.error(e.message)),t.as(r.ExitCode(1)))),t.provide(xa(A.layer)));e.runMain(Ca,{teardown:(e,t)=>{if(n.isSuccess(e)){t(Number(e.value));return}i.defaultTeardown(e,t)}});export{};
|
|
135
|
+
`;return yield*F(t,`${r}${c}${s}`),`updated`}),da=(e,n)=>t.gen(function*(){yield*(yield*Q).withSpinner(()=>Hn(e,n),{failure:`Failed to install dependencies.`,start:`Installing dependencies...`,success:`Dependencies installed.`})});function fa(e,n,r){return t.gen(function*(){let i=yield*Q,a=yield*i.withSpinner(a=>t.gen(function*(){let t=yield*n.detect(e);for(let e of t.warnings)yield*i.log.warning(e);return t.active===null?(yield*a.message(`\`${n.config}\` not found, creating...`),yield*r,{created:!0,legacyConfig:null}):t.active.format===`ts`?(yield*a.message(`Found \`${n.config}\`, keeping existing config.`),{created:!1,legacyConfig:null}):(yield*a.message(`Found \`${t.active.file}\`, keeping existing config.`),{created:!1,legacyConfig:t.active.file})}),{failure:`Failed to set up ${n.name} config.`,start:`Setting up ${n.name} config...`,success:e=>e.created?`${n.name} config created successfully.`:`${n.name} config is ready.`});a.legacyConfig&&(yield*i.log.info(`Legacy \`${a.legacyConfig}\` was preserved during \`adamantite init\`. Run \`adamantite doctor\` and follow its findings to migrate it to the latest ${n.name} config.`))})}const pa=(e,n,r)=>t.gen(function*(){let i=yield*Q,a=yield*R(e),o=r.overwriteScripts?[]:dt(a,n),s=new Set(o.map(e=>e.script)),c=n.filter(e=>!s.has(e));yield*i.withSpinner(()=>t.gen(function*(){if(c.length!==0){a.scripts??={};for(let e of c)a.scripts[e]=z[e];yield*ct(e,a)}}),{failure:"Failed to add scripts to `package.json`.",start:"Adding scripts to your `package.json`...",success:o.length===0?"Scripts added to your `package.json`":c.length===0?"Kept your existing `package.json` scripts.":"Scripts added to your `package.json`; conflicting scripts were kept."});let l=r.nonInteractive?"Use `--overwrite-scripts` to replace it.":"Re-run `adamantite init` and confirm overwriting to replace it.";for(let e of o)yield*i.log.warning(`Kept existing \`${e.script}\` script (\`${e.command}\`) instead of \`${z[e.script]}\`. ${l}`);return o.length>0&&(yield*i.log.info("Adamantite commands forward extra arguments after `--`, so custom flags can be kept, e.g. `adamantite analyze -- --directory packages/app`.")),c}),ma=(e,n)=>t.gen(function*(){let r=yield*Q;n?yield*b(vi,t.forEach(e=>r.log.info(e))):yield*r.withSpinner(n=>t.gen(function*(){return(yield*Z.detect(e))?(yield*n.message(`\`${Z.config}\` found, updating...`),yield*Z.update(e),!1):(yield*n.message(`\`${Z.config}\` not found, creating...`),yield*Z.create(e),!0)}),{failure:`Failed to set up TypeScript config.`,start:`Setting up TypeScript config...`,success:e=>e?`\`${Z.config}\` created successfully`:`\`${Z.config}\` updated successfully`})}),ha=e=>t.gen(function*(){let t=yield*Q,n=yield*Y.update(e);n.prepare===`merged`&&(yield*t.log.info("Added `adamantite prepare` to the start of your existing `prepare` script.")),n.tsconfig===`monorepo`&&(yield*t.log.info("In a monorepo, add the Effect language service entry to each package's `tsconfig.json` or to a shared base config. Run `adamantite doctor` for the reference entry.")),n.tsconfig===`missing`&&(yield*t.log.warning("No `tsconfig.json` found, so the Effect language service is not configured. Run `adamantite doctor` for the reference entry."))}),ga=e=>t.gen(function*(){let n=yield*Q;(yield*Y.detect(e))&&(yield*n.withSpinner(()=>Y.patch(e,{quiet:!0}),{failure:`Failed to patch Oxlint and TypeScript.`,start:`Patching Oxlint and TypeScript with @effect/tsgo...`,success:`Oxlint and TypeScript patched with @effect/tsgo.`}).pipe(t.catchTag([`CommandFailed`,`CliNotFound`,`PlatformError`],()=>n.log.warning("Run `adamantite prepare` to see why the patch failed. Oxlint cannot load the `effect` preset until it succeeds."))))}),_a=(e,n)=>t.gen(function*(){let r=yield*Q;n.includes(`vscode`)&&(yield*r.withSpinner(n=>t.gen(function*(){let t=yield*$.detect(e);return yield*n.message(`\`${$.config}\` ${t?`found, updating`:`not found, creating`}...`),yield*t?$.update(e):$.create(e),!t}),{failure:`Failed to set up VS Code config.`,start:`Checking for \`${$.config}\`...`,success:e=>`\`${$.config}\` ${e?`created`:`updated`} with Adamantite preset.`})),n.includes(`zed`)&&(yield*r.withSpinner(n=>t.gen(function*(){let t=yield*K.detect(e);return yield*n.message(`\`${K.config}\` ${t?`found, updating`:`not found, creating`}...`),yield*t?K.update(e):K.create(e),!t}),{failure:`Failed to set up Zed config.`,start:`Checking for \`${K.config}\`...`,success:e=>`\`${K.config}\` ${e?`created`:`updated`} with Adamantite preset.`}))}),va=(e,n)=>t.gen(function*(){let r=yield*Q,i=e.includes(`zed`),a=e.includes(`vscode`);yield*r.withSpinner(e=>t.gen(function*(){return a&&(yield*e.message(`Installing VS Code extension...`),yield*$.extension(n)),!0}),{start:`Installing editor extensions...`,success:i&&!a?`Zed extensions require manual install.`:`Editor extensions installed successfully.`}).pipe(t.catchTags({FailedToInstallExtension:e=>t.gen(function*(){return yield*r.log.warning(`⚠️ ${e.message}`),yield*r.log.warning(`Please install it manually after setup completes.`),!1}),VscodeCliNotFound:()=>t.gen(function*(){return yield*r.log.error(`VSCode CLI ('code' command) not found.`),yield*r.log.info(`To install it:`),yield*r.log.info(` 1. Open VS Code`),yield*r.log.info(` 2. Press Cmd+Shift+P (macOS) or Ctrl+Shift+P (Windows/Linux)`),yield*r.log.info(` 3. Run 'Shell Command: Install "code" command in PATH'`),!1})})),i&&(yield*r.log.info("Install the Zed `oxc` extension: zed://extension/oxc"))}),ya=(e,n,r)=>t.gen(function*(){let i=yield*Q,a=pr.files[0].path;yield*i.withSpinner(i=>t.gen(function*(){let t=yield*pr.detect(e);return yield*i.message(t?`\`${a}\` found, updating...`:`Creating \`${a}\`...`),yield*t?pr.update(e,{packageManager:n,scripts:r}):pr.create(e,{packageManager:n,scripts:r}),!t}),{failure:`Failed to set up GitHub Actions workflow.`,start:`Setting up GitHub Actions workflow...`,success:e=>`GitHub Actions workflow ${e?`created`:`updated`} successfully.`})}).pipe(t.catchTag([`FailedToCreateDirectory`,`FailedToParseFile`,`FailedToReadFile`,`FailedToWriteFile`,`PlatformError`],e=>t.gen(function*(){let t=yield*Q;yield*t.log.warning(`Could not set up the GitHub Actions workflow. ${e.message}`),yield*t.log.warning("Fix the reported problem and run `adamantite init` again, or create the workflow manually.")}))),ba=(e,n,r,i)=>t.gen(function*(){let a=yield*Q,o=yield*a.withSpinner(()=>ua(e,{isMonorepo:i,packageManager:n,scripts:r}),{failure:`Failed to update AGENTS.md.`,start:`Updating AGENTS.md...`,success:`AGENTS.md check complete.`}).pipe(t.catchTag([`FailedToReadFile`,`FailedToWriteFile`],e=>t.gen(function*(){return yield*a.log.warning(`Could not update AGENTS.md. ${e.message} Adamantite will continue initialization.`),`failed`})));o!==`failed`&&o===`malformed`&&(yield*a.log.warning(`Could not update AGENTS.md because Adamantite markers are incomplete. Remove the stale ADAMANTITE marker and run adamantite init again.`))});var xa=c.make(`init`,ta).pipe(c.withDescription(`Initialize Adamantite in the current directory. Setup flags require --non-interactive; omitted boolean setup flags are disabled`),c.withExamples([{command:`adamantite init --non-interactive --script check`,description:`Configure linting without prompts`},{command:`adamantite init --non-interactive --script check --preset react --editor vscode --typescript --install-extensions --github-actions --agents`,description:`Configure a React project with VS Code, TypeScript, CI, and agent guidance`},{command:`adamantite init --non-interactive --script analyze`,description:`Configure analysis; in a detected monorepo it includes Sherif`}]),c.withHandler(e=>t.gen(function*(){let t=f.cwd(),n=yield*Q;yield*Wi,yield*n.intro(`💠 adamantite init`);let r=yield*(yield*Bn).detectPackageManager(t);if(!r)return yield*new Ie({});if(r.warnings?.length)for(let e of r.warnings)yield*n.log.warning(e);yield*n.log.info(`Detected package manager: ${r.name}`);let i=yield*B(t);if(i&&(yield*n.log.info(`We've detected a monorepo setup in your project.`)),!e.nonInteractive&&s.some([e.scripts.length>0,e.presets.length>0,e.editors.length>0,e.typescript,e.installExtensions,e.githubActions,e.agents,e.overwriteScripts],x.isTruthy))return yield*new A({reason:"Setup flags require `--non-interactive`."});let a=e.nonInteractive?e:yield*ra(t,i),o=yield*qi(a,{nonInteractive:e.nonInteractive,packageManager:r.name}),c=o.scripts,l=o.presets,u=o.editors,d=o.typescript,p=o.installExtensions,m=o.githubActions,h=o.agents,g=c.includes(`check`)||c.includes(`fix`),_=c.includes(`analyze`),v=_&&i,y=yield*R(t),b=x.isNotUndefined(y.devDependencies?.adamantite??y.dependencies?.adamantite)?[]:[`adamantite`];g&&b.push(`${W.name}@${W.version}`,`${hi.name}@${hi.version}`,`${U.name}@${U.version}`,...mi.filter(e=>l.includes(e.preset)).map(e=>`${e.name}@${e.version}`)),v&&b.push(`${H.name}@${H.version}`),_&&b.push(`${V.name}@${V.version}`),yield*da(t,b),g&&(yield*fa(t,U,U.create(t)),yield*fa(t,W,W.create(t,l))),_&&(yield*fa(t,V,V.create(t)));let S=yield*pa(t,c,{nonInteractive:e.nonInteractive,overwriteScripts:o.overwriteScripts});if(h&&(yield*ba(t,r.name,S,i)),d&&(yield*ma(t,i)),l.includes(`effect`)&&(yield*ha(t)),g&&(yield*ga(t)),yield*_a(t,u),p&&(yield*va(u,c)),m){let e=r.name;lt(e)?yield*ya(t,e,c):yield*n.log.warning(`Skipping GitHub Actions setup: \`${e}\` is not a supported package manager for CI workflow generation.`)}yield*n.log.success(`Your project is now configured`),yield*n.outro(`💠 Adamantite initialized successfully!`)}).pipe(t.catchTags({OperationCancelled:()=>t.gen(function*(){yield*(yield*Q).cancel(`You've cancelled the initialization process.`)})})))),Sa=c.make(`prepare`).pipe(c.withDescription("Patch Oxlint and TypeScript for the effect preset. The `prepare` script runs it after each install"),c.withHandler(()=>t.gen(function*(){let e=f.cwd();(yield*Y.detect(e))&&(yield*Y.patch(e,{quiet:!1}))})));const Ca=T.File(`file`,{mustExist:!0}).pipe(T.withDescription(`The JavaScript or TypeScript file to parse`)),wa=c.make(`ast`,{file:Ca}).pipe(c.withDescription(`Print the ESTree-shaped AST that Oxlint rules visit, to find node names for a custom rule`),c.withHandler(({file:e})=>t.gen(function*(){let t=yield*Q,n=yield*N(e),r=de(e,n,{preserveParens:!1});if(r.errors.length>0)return yield*new ke({errors:r.errors.map(e=>e.message),path:e});yield*t.message(JSON.stringify(r.program,null,2))}))),Ta=T.String(`name`).pipe(T.withDescription(`The rule name in kebab-case, such as no-process-env`)),Ea=u.String(`dir`).pipe(u.optional,u.withDescription(`The rules folder, relative to the current directory. Default: ${Fr}. Pass the folder that \`custom({ dir })\` loads, such as a rules folder in a monorepo tooling package`)),Da=c.make(`add`,{dir:Ea,name:Ta}).pipe(c.withDescription(`Write a custom rule stub, and the authoring guidance when the rules folder has none`),c.withHandler(({dir:e,name:n})=>t.gen(function*(){let t=yield*Q,r=yield*w.Path,i=f.cwd(),a=yield*Rr(i,n,d.getOrUndefined(e));yield*t.log.success(`Wrote ${r.relative(i,a.rulePath)}.`),a.agentsPath!==void 0&&(yield*t.log.success(`Wrote ${r.relative(i,a.agentsPath)}.`)),yield*t.log.info("`custom()` from `adamantite/lint/custom` loads the rule. Run `adamantite doctor` to check the wiring.")})));var Oa=c.make(`rule`).pipe(c.withDescription(`Write and inspect custom Oxlint rules`),c.withSubcommands([Da,wa]));const ka=[W,hi,U,H,V];function Aa(e,t){return s.filterMap(ka,n=>{if(t.has(n.name))return v.failVoid;let r=e.devDependencies?.[n.name]??e.dependencies?.[n.name];return r&&st(r)!==n.version?v.succeed({currentVersion:r,name:n.name,targetVersion:n.version}):v.failVoid})}var ja=c.make(`update`).pipe(c.withDescription(`Update Adamantite-managed dependencies and report setup findings`),c.withHandler(()=>t.gen(function*(){let e=f.cwd(),t=yield*Q;yield*t.intro(`💠 adamantite update`);let n=yield*R(e),r=yield*Ci(e,n),i=r.packageActions,a=new Set(i.map(e=>e.package)),o=[...i.map(e=>({currentVersion:e.type===`install_package`?`not installed`:e.currentVersion,name:e.package,targetVersion:e.targetVersion})),...Aa(n,a)];if(o.length>0){yield*t.log.info(`The following dependencies will be updated:`);for(let e of o)yield*t.log.info(` ${e.name}: ${e.currentVersion} → ${e.targetVersion}`);yield*t.withSpinner(()=>Hn(e,o.map(e=>`${e.name}@${e.targetVersion}`)),{failure:`Failed to update dependencies`,start:`Updating dependencies...`,success:`Dependencies updated successfully`}),yield*t.log.success(`Dependencies updated successfully.`),(yield*Y.detect(e))&&(yield*t.withSpinner(()=>Y.patch(e,{quiet:!0}),{failure:"Failed to patch Oxlint and TypeScript. Run `adamantite prepare` to see why.",start:`Patching Oxlint and TypeScript with @effect/tsgo...`,success:`Oxlint and TypeScript patched with @effect/tsgo.`}))}let s=o.length===0?r:yield*Ci(e);for(let e of s.warnings)yield*t.log.warning(e);let c=s.findings;return c.length>0&&(yield*Pi(c),yield*t.log.info("Run `adamantite doctor` to get the combined Markdown repair prompt.")),o.length===0&&c.length===0?(yield*t.log.success(`No changes needed.`),`no-changes`):`success`}).pipe(t.tapError(()=>t.gen(function*(){yield*(yield*Q).outro(`❌ Update failed`)})),t.tap(e=>t.gen(function*(){yield*(yield*Q).outro(e===`no-changes`?`✅ Adamantite is already up to date.`:`✅ Update completed successfully!`)})))));const Ma=[Tn,In,Hi],Na=[Tn,In,Ii,Hi,xa,Sa,Oa,ja],Pa=new Set(Na.map(e=>e.name)),Fa=new Set(Ma.map(e=>e.name)),Ia=c.make(`adamantite`).pipe(c.withDescription(`Opinionated preset package for modern TypeScript applications`),c.withSubcommands(Na)),La=e=>l.mergeAll(o.layer,Qn.layer.pipe(l.provide(o.layer)),Q.layer,ji.layer.pipe(l.provideMerge(e),l.provide(o.layer)),Bn.layer,Mi.layer),Ra=t.fn(`runCli`)(function*(e,n){let[r,i]=s.splitWhere(e,e=>e===`--`),a=s.drop(i,1),o=r.find(e=>Pa.has(e));if(a.length>0&&o!==void 0&&!Fa.has(o))return yield*new Re({command:o});yield*c.runWith(Ia,{version:n})(r).pipe(t.provideService(Ue,a))}),za=t.gen(function*(){let e=yield*(yield*a.Stdio).args;yield*Ra(e,`0.44.0`)}).pipe(t.as(0),t.catchTag(`CommandFailed`,e=>t.succeed(e.exitCode)),t.catch(e=>t.service(Q).pipe(t.flatMap(t=>t.log.error(e.message)),t.as(r.ExitCode(1)))),t.provide(La(j.layer)));e.runMain(za,{teardown:(e,t)=>{n.isSuccess(e)?t(Number(e.value)):i.defaultTeardown(e,t)}});export{};
|
|
@@ -7,6 +7,7 @@ const config = {
|
|
|
7
7
|
"effecttsgo/class-self-mismatch": "error",
|
|
8
8
|
"effecttsgo/duplicate-package": "error",
|
|
9
9
|
"effecttsgo/effect-fn-implicit-any": "error",
|
|
10
|
+
"effecttsgo/error-payload-shadows-name": "error",
|
|
10
11
|
"effecttsgo/experimental-api-usage": "error",
|
|
11
12
|
"effecttsgo/floating-effect": "error",
|
|
12
13
|
"effecttsgo/floating-effect-in-vitest": "error",
|
|
@@ -22,6 +23,8 @@ const config = {
|
|
|
22
23
|
"effecttsgo/outdated-api": "error",
|
|
23
24
|
"effecttsgo/overridden-schema-constructor": "error",
|
|
24
25
|
"effecttsgo/promise-in-effect-success": "error",
|
|
26
|
+
"effecttsgo/schema-class-missing-brand": "error",
|
|
27
|
+
"effecttsgo/schema-class-object-literal": "error",
|
|
25
28
|
"effecttsgo/schema-literal-non-finite": "error",
|
|
26
29
|
"effecttsgo/schema-opaque-instance-member": "error",
|
|
27
30
|
"effecttsgo/unsafe-effect-type-assertion": "error",
|
|
@@ -70,10 +73,12 @@ const config = {
|
|
|
70
73
|
"effecttsgo/effect-fn-opportunity": "error",
|
|
71
74
|
"effecttsgo/effect-map-flatten": "error",
|
|
72
75
|
"effecttsgo/effect-map-void": "error",
|
|
76
|
+
"effecttsgo/effect-sleep-zero-to-yield-now": "error",
|
|
73
77
|
"effecttsgo/effect-succeed-with-void": "error",
|
|
74
78
|
"effecttsgo/flat-map-conditional-to-filter-or-fail": "error",
|
|
75
79
|
"effecttsgo/flat-map-ignored-param-to-and-then": "error",
|
|
76
80
|
"effecttsgo/flat-map-to-map": "error",
|
|
81
|
+
"effecttsgo/flat-map-to-tap": "error",
|
|
77
82
|
"effecttsgo/map-some-to-as-some": "error",
|
|
78
83
|
"effecttsgo/match-effect-to-map-both": "error",
|
|
79
84
|
"effecttsgo/match-effect-to-match": "error",
|
|
@@ -17,7 +17,7 @@ const config = {
|
|
|
17
17
|
"jest/no-duplicate-hooks": "error",
|
|
18
18
|
"jest/no-export": "error",
|
|
19
19
|
"jest/no-focused-tests": "error",
|
|
20
|
-
"jest/no-hooks": "
|
|
20
|
+
"jest/no-hooks": "off",
|
|
21
21
|
"jest/no-identical-title": "error",
|
|
22
22
|
"jest/no-interpolation-in-snapshots": "error",
|
|
23
23
|
"jest/no-jasmine-globals": "error",
|
|
@@ -37,7 +37,11 @@ const config = {
|
|
|
37
37
|
"jest/prefer-each": "error",
|
|
38
38
|
"jest/prefer-ending-with-an-expect": "error",
|
|
39
39
|
"jest/prefer-equality-matcher": "error",
|
|
40
|
-
"jest/prefer-expect-assertions": "error",
|
|
40
|
+
"jest/prefer-expect-assertions": ["error", {
|
|
41
|
+
onlyFunctionsWithAsyncKeyword: true,
|
|
42
|
+
onlyFunctionsWithExpectInCallback: true,
|
|
43
|
+
onlyFunctionsWithExpectInLoop: true
|
|
44
|
+
}],
|
|
41
45
|
"jest/prefer-expect-resolves": "error",
|
|
42
46
|
"jest/prefer-hooks-in-order": "error",
|
|
43
47
|
"jest/prefer-hooks-on-top": "error",
|
|
@@ -15,28 +15,50 @@ const config = {
|
|
|
15
15
|
"vitest/no-disabled-tests": "error",
|
|
16
16
|
"vitest/no-duplicate-hooks": "error",
|
|
17
17
|
"vitest/no-focused-tests": "error",
|
|
18
|
-
"vitest/no-hooks": "
|
|
18
|
+
"vitest/no-hooks": "off",
|
|
19
19
|
"vitest/no-identical-title": "error",
|
|
20
20
|
"vitest/no-import-node-test": "error",
|
|
21
|
-
"vitest/no-importing-vitest-globals": "
|
|
21
|
+
"vitest/no-importing-vitest-globals": "off",
|
|
22
22
|
"vitest/no-interpolation-in-snapshots": "error",
|
|
23
23
|
"vitest/no-large-snapshots": "error",
|
|
24
24
|
"vitest/no-mocks-import": "error",
|
|
25
25
|
"vitest/no-restricted-matchers": "error",
|
|
26
|
-
"vitest/no-standalone-expect": "error",
|
|
26
|
+
"vitest/no-standalone-expect": ["error", { additionalTestBlockFunctions: [
|
|
27
|
+
"it.effect",
|
|
28
|
+
"it.effect.each",
|
|
29
|
+
"it.effect.fails",
|
|
30
|
+
"it.effect.only",
|
|
31
|
+
"it.effect.prop",
|
|
32
|
+
"it.effect.runIf",
|
|
33
|
+
"it.effect.skip",
|
|
34
|
+
"it.effect.skipIf",
|
|
35
|
+
"it.live",
|
|
36
|
+
"it.live.each",
|
|
37
|
+
"it.live.fails",
|
|
38
|
+
"it.live.only",
|
|
39
|
+
"it.live.prop",
|
|
40
|
+
"it.live.runIf",
|
|
41
|
+
"it.live.skip",
|
|
42
|
+
"it.live.skipIf",
|
|
43
|
+
"it.prop"
|
|
44
|
+
] }],
|
|
27
45
|
"vitest/no-test-prefixes": "error",
|
|
28
46
|
"vitest/no-test-return-statement": "error",
|
|
29
47
|
"vitest/no-unneeded-async-expect-function": "error",
|
|
30
48
|
"vitest/padding-around-test-blocks": "error",
|
|
31
49
|
"vitest/prefer-called-exactly-once-with": "error",
|
|
32
50
|
"vitest/prefer-called-once": "error",
|
|
33
|
-
"vitest/prefer-called-times": "
|
|
51
|
+
"vitest/prefer-called-times": "off",
|
|
34
52
|
"vitest/prefer-called-with": "error",
|
|
35
53
|
"vitest/prefer-comparison-matcher": "error",
|
|
36
|
-
"vitest/prefer-describe-function-title": "
|
|
54
|
+
"vitest/prefer-describe-function-title": "off",
|
|
37
55
|
"vitest/prefer-each": "error",
|
|
38
56
|
"vitest/prefer-equality-matcher": "error",
|
|
39
|
-
"vitest/prefer-expect-assertions": "error",
|
|
57
|
+
"vitest/prefer-expect-assertions": ["error", {
|
|
58
|
+
onlyFunctionsWithAsyncKeyword: true,
|
|
59
|
+
onlyFunctionsWithExpectInCallback: true,
|
|
60
|
+
onlyFunctionsWithExpectInLoop: true
|
|
61
|
+
}],
|
|
40
62
|
"vitest/prefer-expect-resolves": "error",
|
|
41
63
|
"vitest/prefer-expect-type-of": "error",
|
|
42
64
|
"vitest/prefer-hooks-in-order": "error",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adamantite",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.44.0",
|
|
4
4
|
"description": "An strict and opinionated set of presets for modern TypeScript applications",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"adamantite",
|
|
@@ -62,37 +62,38 @@
|
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
64
|
"@clack/prompts": "1.8.1",
|
|
65
|
-
"@effect/platform-node": "4.0.
|
|
66
|
-
"@
|
|
65
|
+
"@effect/platform-node": "4.0.5",
|
|
66
|
+
"@effect/platform-node-shared": "4.0.5",
|
|
67
|
+
"@oxlint/plugins": "1.88.0",
|
|
67
68
|
"defu": "6.1.7",
|
|
68
|
-
"effect": "4.0.
|
|
69
|
+
"effect": "4.0.5",
|
|
69
70
|
"jsonc-parser": "3.3.1",
|
|
70
71
|
"nypm": "0.6.10",
|
|
71
|
-
"oxc-parser": "0.
|
|
72
|
+
"oxc-parser": "0.154.0"
|
|
72
73
|
},
|
|
73
74
|
"devDependencies": {
|
|
74
75
|
"@changesets/changelog-github": "1.0.1",
|
|
75
76
|
"@changesets/cli": "3.0.3",
|
|
76
|
-
"@effect/tsgo": "0.
|
|
77
|
-
"@effect/vitest": "4.0.
|
|
78
|
-
"@shadcn/lint": "0.2.
|
|
79
|
-
"@tanstack/intent": "0.5.
|
|
77
|
+
"@effect/tsgo": "0.54.0",
|
|
78
|
+
"@effect/vitest": "4.0.5",
|
|
79
|
+
"@shadcn/lint": "0.2.1",
|
|
80
|
+
"@tanstack/intent": "0.5.5",
|
|
80
81
|
"@types/figlet": "1.7.0",
|
|
81
82
|
"@types/node": "22.20.5",
|
|
82
|
-
"@vitest/coverage-v8": "5.0.
|
|
83
|
-
"@vitest/ui": "5.0.
|
|
83
|
+
"@vitest/coverage-v8": "5.0.5",
|
|
84
|
+
"@vitest/ui": "5.0.5",
|
|
84
85
|
"figlet": "1.12.0",
|
|
85
|
-
"knip": "6.
|
|
86
|
-
"oxfmt": "0.
|
|
87
|
-
"oxlint": "1.
|
|
88
|
-
"oxlint-plugin-react-doctor": "0.9.
|
|
89
|
-
"oxlint-tsgolint": "7.0.
|
|
86
|
+
"knip": "6.42.0",
|
|
87
|
+
"oxfmt": "0.73.0",
|
|
88
|
+
"oxlint": "1.88.0",
|
|
89
|
+
"oxlint-plugin-react-doctor": "0.9.18",
|
|
90
|
+
"oxlint-tsgolint": "7.0.2004",
|
|
90
91
|
"sherif": "1.13.0",
|
|
91
|
-
"tsdown": "0.23.
|
|
92
|
+
"tsdown": "0.23.1",
|
|
92
93
|
"type-fest": "5.10.0",
|
|
93
94
|
"typescript": "7.0.2",
|
|
94
|
-
"unplugin-macros": "0.23.
|
|
95
|
-
"vitest": "5.0.
|
|
95
|
+
"unplugin-macros": "0.23.3",
|
|
96
|
+
"vitest": "5.0.5"
|
|
96
97
|
},
|
|
97
98
|
"peerDependencies": {
|
|
98
99
|
"typescript": ">=7"
|
|
@@ -104,6 +105,7 @@
|
|
|
104
105
|
"scripts": {
|
|
105
106
|
"analyze": "knip",
|
|
106
107
|
"build": "tsdown",
|
|
108
|
+
"build:verify": "pnpm run build && pnpm run test:build",
|
|
107
109
|
"bump:deps": "pnpm update --interactive --latest",
|
|
108
110
|
"check": "oxlint",
|
|
109
111
|
"dev": "tsdown --watch",
|
|
@@ -76,7 +76,9 @@ install instead of changing the script. `tsconfig.json` needs
|
|
|
76
76
|
`{ "name": "@effect/language-service", "diagnostics": false }` in `compilerOptions.plugins`,
|
|
77
77
|
and `knip.config.ts` needs `ignoreDependencies.effect`. To allow an unstable Effect module
|
|
78
78
|
on purpose, add it to `allowedUnstableApis` in that tsconfig entry. Do not turn off
|
|
79
|
-
`effecttsgo/unstable-api-usage`.
|
|
79
|
+
`effecttsgo/unstable-api-usage`. In Effect 4.0.2 and later, the platform modules (such as
|
|
80
|
+
`effect/FileSystem` and `effect/Path`), `@effect/platform-node`, and `@effect/vitest` are
|
|
81
|
+
unstable. An entry can be a module or a full package.
|
|
80
82
|
|
|
81
83
|
The `shadcn` preset needs Tailwind v4 and the `@shadcn/lint` package, which `init` installs
|
|
82
84
|
at a pinned version and doctor and `update` keep in sync. The plugin finds components and
|