@danieljvdm/dev-kit 0.18.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +148 -659
  2. package/package.json +8 -62
  3. package/skill-sources.jsonc +1 -0
  4. package/skill-sources.lock.json +5 -1
  5. package/skills/dev-kit/SKILL.md +42 -212
  6. package/skills/dev-kit/agents/openai.yaml +2 -2
  7. package/skills/dev-kit/references/cloudflare-worker-api.md +37 -0
  8. package/skills/dev-kit/references/default-typescript-repository.md +43 -0
  9. package/skills/dev-kit/references/legacy-eject.md +46 -0
  10. package/skills/dev-kit/references/repository-setup.md +53 -0
  11. package/skills/dev-kit/references/skills.md +35 -0
  12. package/src/bin/dev-kit.ts +142 -127
  13. package/src/eject.ts +715 -0
  14. package/src/legacy-project.ts +67 -0
  15. package/src/oxfmt.ts +1 -4
  16. package/src/oxlint.ts +5 -10
  17. package/src/path-digest.ts +60 -0
  18. package/src/project-skills.ts +722 -0
  19. package/src/tool-metadata.ts +0 -2
  20. package/src/vendor.ts +0 -5
  21. package/src/vite-plus.ts +1 -3
  22. package/dev-kit.example.jsonc +0 -22
  23. package/schema/dev-kit.schema.json +0 -218
  24. package/schema/skill-sources.schema.json +0 -83
  25. package/scripts/sync-anti-slop-runtime.mjs +0 -19
  26. package/src/index.ts +0 -125
  27. package/src/manifest.ts +0 -224
  28. package/src/oxfmt.js +0 -23
  29. package/src/oxlint-plugin-anti-slop/runtime.d.ts +0 -22
  30. package/src/oxlint-plugin-effect.d.ts +0 -19
  31. package/src/oxlint-plugin-style.d.ts +0 -8
  32. package/src/oxlint.js +0 -113
  33. package/src/project-state.ts +0 -122
  34. package/src/scaffold.ts +0 -79
  35. package/src/skill-manager.ts +0 -527
  36. package/src/sync.ts +0 -1935
  37. package/src/tool-ignore-patterns.js +0 -9
  38. package/src/vite-plus-dependency.ts +0 -69
  39. package/src/vite-plus-hooks.ts +0 -175
  40. package/src/vite-plus-workflow.ts +0 -82
  41. package/src/vite-plus.js +0 -88
  42. package/src/worktrunk-config.ts +0 -88
  43. package/templates/AGENTS.md +0 -11
  44. package/templates/vite-plus/github-actions-check.yml +0 -51
  45. package/templates/worktrunk/wt.toml +0 -27
@@ -0,0 +1,67 @@
1
+ import { Schema } from "effect";
2
+
3
+ import { DigestSchema } from "./path-digest.ts";
4
+
5
+ const EnabledSetupSchema = Schema.Struct({
6
+ enabled: Schema.optional(Schema.Boolean),
7
+ });
8
+
9
+ export const LegacyDevKitManifestSchema = Schema.Struct({
10
+ setup: Schema.optional(
11
+ Schema.Struct({
12
+ effectSource: Schema.optional(EnabledSetupSchema),
13
+ effectTsgo: Schema.optional(EnabledSetupSchema),
14
+ vitePlus: Schema.optional(
15
+ Schema.Struct({
16
+ hooks: Schema.optional(EnabledSetupSchema),
17
+ }),
18
+ ),
19
+ }),
20
+ ),
21
+ });
22
+
23
+ export type LegacyDevKitManifest = typeof LegacyDevKitManifestSchema.Type;
24
+
25
+ export const legacySetupFlags = (manifest: LegacyDevKitManifest) => ({
26
+ effectSource: manifest.setup?.effectSource?.enabled ?? false,
27
+ effectTsgo: manifest.setup?.effectTsgo?.enabled ?? false,
28
+ vitePlusHooks: manifest.setup?.vitePlus?.hooks?.enabled ?? false,
29
+ });
30
+
31
+ const LegacyCatalogProvenanceSchema = Schema.Union([
32
+ Schema.Struct({
33
+ source: Schema.String,
34
+ repository: Schema.String,
35
+ resolved: Schema.String,
36
+ }),
37
+ Schema.Struct({
38
+ package: Schema.String,
39
+ version: Schema.String,
40
+ skill: Schema.String,
41
+ digest: DigestSchema,
42
+ }),
43
+ ]);
44
+
45
+ export const LegacyManagedSkillOutputSchema = Schema.Struct({
46
+ resourceId: Schema.String,
47
+ path: Schema.String,
48
+ skill: Schema.String,
49
+ target: Schema.Literals(["agents", "claude", "opencode"]),
50
+ mode: Schema.Literals(["copy", "symlink"]),
51
+ kind: Schema.Literals(["directory", "symlink"]),
52
+ digest: DigestSchema,
53
+ catalog: Schema.optional(LegacyCatalogProvenanceSchema),
54
+ });
55
+
56
+ export type LegacyManagedSkillOutput = typeof LegacyManagedSkillOutputSchema.Type;
57
+
58
+ const LegacyOtherOutputSchema = Schema.Struct({
59
+ resourceId: Schema.String,
60
+ path: Schema.String,
61
+ });
62
+
63
+ export const LegacyDevKitLockSchema = Schema.Struct({
64
+ version: Schema.Literal(1),
65
+ toolVersion: Schema.String,
66
+ outputs: Schema.Array(Schema.Union([LegacyManagedSkillOutputSchema, LegacyOtherOutputSchema])),
67
+ });
package/src/oxfmt.ts CHANGED
@@ -5,10 +5,7 @@ import { devKitToolIgnorePatterns } from "./tool-ignore-patterns.ts";
5
5
  export { devKitToolIgnorePatterns } from "./tool-ignore-patterns.ts";
6
6
 
7
7
  /**
8
- * Canonical formatting defaults for standalone Oxfmt and Vite+ projects.
9
- *
10
- * Oxfmt does not support config inheritance. Spread this object into a
11
- * standalone Oxfmt config or Vite+'s `fmt` block before local overrides.
8
+ * Formatting defaults for this repository's Vite+ config.
12
9
  */
13
10
  export const recommendedOxfmtConfig = {
14
11
  arrowParens: "always",
package/src/oxlint.ts CHANGED
@@ -12,8 +12,7 @@ export type AbsoluteImportsOptions = {
12
12
  /**
13
13
  * Build an Oxlint override that forbids `../` imports inside the given globs,
14
14
  * so those files import through tsconfig path aliases such as `@/*`. Append it
15
- * to a standalone Oxlint config's `overrides`, or opt in through
16
- * `createRecommendedVitePlusConfig({ absoluteImports })`.
15
+ * to this repository's Oxlint overrides.
17
16
  */
18
17
  export const createAbsoluteImportsOxlintOverride = (options: AbsoluteImportsOptions) => {
19
18
  if (options.files.length === 0) {
@@ -39,11 +38,7 @@ export const createAbsoluteImportsOxlintOverride = (options: AbsoluteImportsOpti
39
38
  };
40
39
 
41
40
  /**
42
- * High-signal Oxlint defaults for TypeScript projects.
43
- *
44
- * Extend this object from standalone Oxlint's `extends`, or from Vite+'s
45
- * `lint.extends`, so project-local plugins, rules, and overrides compose
46
- * without losing nested configuration.
41
+ * High-signal Oxlint defaults for this repository.
47
42
  */
48
43
  export const recommendedOxlintConfig = {
49
44
  ignorePatterns: [...devKitToolIgnorePatterns],
@@ -53,15 +48,15 @@ export const recommendedOxlintConfig = {
53
48
  jsPlugins: [
54
49
  {
55
50
  name: "anti-slop",
56
- specifier: "@danieljvdm/dev-kit/oxlint-plugin-anti-slop",
51
+ specifier: "./src/oxlint-plugin-anti-slop/runtime.js",
57
52
  },
58
53
  {
59
54
  name: "effect",
60
- specifier: "@danieljvdm/dev-kit/oxlint-plugin-effect",
55
+ specifier: "./src/oxlint-plugin-effect.js",
61
56
  },
62
57
  {
63
58
  name: "stylistic",
64
- specifier: "@danieljvdm/dev-kit/oxlint-plugin-style",
59
+ specifier: "./src/oxlint-plugin-style.js",
65
60
  },
66
61
  ],
67
62
  plugins: ["import", "react", "vitest"],
@@ -153,6 +153,66 @@ export const observePath = Effect.fn("observeManagedPath")(function* (absolutePa
153
153
  );
154
154
  });
155
155
 
156
+ export const observeDirectoryWithoutEntry = Effect.fn("observeDirectoryWithoutEntry")(function* (
157
+ absolutePath: string,
158
+ excludedEntry: string,
159
+ ) {
160
+ const fs = yield* FileSystem.FileSystem;
161
+ const path = yield* Path.Path;
162
+
163
+ if (
164
+ excludedEntry.length === 0 ||
165
+ excludedEntry === "." ||
166
+ excludedEntry === ".." ||
167
+ excludedEntry.includes("/") ||
168
+ excludedEntry.includes("\\")
169
+ ) {
170
+ return yield* PathInspectionError.make({
171
+ path: absolutePath,
172
+ operation: "exclude a direct directory entry",
173
+ cause: excludedEntry,
174
+ });
175
+ }
176
+ const observed = yield* observeSymbolicLink(absolutePath);
177
+
178
+ if (observed.kind === "missing") return { kind: "missing" } as const;
179
+ if (observed.kind === "symlink") {
180
+ return yield* PathInspectionError.make({
181
+ path: absolutePath,
182
+ operation: "inspect a regular directory",
183
+ cause: "path is a symlink",
184
+ });
185
+ }
186
+ const info = yield* fs.stat(absolutePath);
187
+
188
+ if (info.type !== "Directory") {
189
+ return yield* PathInspectionError.make({
190
+ path: absolutePath,
191
+ operation: "inspect a regular directory",
192
+ cause: info.type,
193
+ });
194
+ }
195
+ const entries = (yield* fs.readDirectory(absolutePath))
196
+ .filter((entry) => entry !== excludedEntry)
197
+ .sort(compareUtf8);
198
+ const frames: Array<string | Uint8Array> = ["directory-v1"];
199
+
200
+ for (const entry of entries) {
201
+ const child = yield* digestFileSystemPath(path.join(absolutePath, entry), canonicalFileMode);
202
+
203
+ if (child.kind === "missing") {
204
+ return yield* PathInspectionError.make({
205
+ path: path.join(absolutePath, entry),
206
+ operation: "inspect a stable directory tree",
207
+ cause: "path disappeared during inspection",
208
+ });
209
+ }
210
+ frames.push(entry, child.kind, child.digest);
211
+ }
212
+
213
+ return { kind: "directory", digest: yield* digestFrames(frames) } as const;
214
+ });
215
+
156
216
  export const digestText = Effect.fn("digestText")(function* (value: string) {
157
217
  return yield* digestFrames(["text-v1", value]);
158
218
  });