@dowel-ui/registry 0.1.0 → 0.1.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 (2) hide show
  1. package/package.json +6 -5
  2. package/src/build.test.ts +0 -131
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@dowel-ui/registry",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "description": "Registry schema and the build that emits the public registry JSON.",
6
6
  "files": [
7
7
  "dist",
8
- "src"
8
+ "src",
9
+ "!src/**/*.test.ts"
9
10
  ],
10
11
  "exports": {
11
12
  ".": {
@@ -25,9 +26,9 @@
25
26
  "tsx": "4.23.13",
26
27
  "typescript": "6.0.3",
27
28
  "vitest": "4.1.10",
28
- "@dowel-ui/themes": "0.1.0",
29
- "@dowel-ui/config": "0.1.0",
30
- "@dowel-ui/react": "0.1.0"
29
+ "@dowel-ui/themes": "0.1.1",
30
+ "@dowel-ui/config": "0.1.1",
31
+ "@dowel-ui/react": "0.1.1"
31
32
  },
32
33
  "scripts": {
33
34
  "build": "tsdown && tsx src/build.ts --out r",
package/src/build.test.ts DELETED
@@ -1,131 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
-
3
- import { buildIndex, buildRegistry } from "./build";
4
- import { hashContent } from "./hash";
5
- import { registryIndexSchema, registryItemSchema } from "./schema";
6
-
7
- /**
8
- * The registry is the boundary with every consumer's project, so these tests
9
- * check the shape and the invariants the CLI relies on — not the contents of
10
- * any particular component.
11
- */
12
-
13
- const items = buildRegistry();
14
-
15
- describe("hashContent", () => {
16
- it("produces a stable prefixed sha256", () => {
17
- expect(hashContent("hello")).toMatch(/^sha256:[0-9a-f]{64}$/);
18
- expect(hashContent("hello")).toBe(hashContent("hello"));
19
- });
20
-
21
- it("distinguishes different content", () => {
22
- expect(hashContent("a")).not.toBe(hashContent("b"));
23
- });
24
-
25
- it("ignores line endings, so a Windows checkout is not all modified", () => {
26
- expect(hashContent("a\r\nb")).toBe(hashContent("a\nb"));
27
- });
28
- });
29
-
30
- describe("buildRegistry", () => {
31
- it("emits every item in the published shape", () => {
32
- for (const item of items) {
33
- expect(() => registryItemSchema.parse(item)).not.toThrow();
34
- }
35
- });
36
-
37
- it("includes the two items init depends on", () => {
38
- const names = items.map((item) => item.name);
39
- expect(names).toContain("utils");
40
- expect(names).toContain("theme");
41
- });
42
-
43
- it("ships the components as registry:ui items", () => {
44
- const button = items.find((item) => item.name === "button");
45
- expect(button?.type).toBe("registry:ui");
46
- expect(button?.files[0]?.path).toBe("ui/button.tsx");
47
- });
48
-
49
- it("ships the tokens as a style item, not a file to write", () => {
50
- const theme = items.find((item) => item.name === "theme");
51
- expect(theme?.files[0]?.type).toBe("registry:style");
52
- expect(theme?.files[0]?.content).toContain("@theme");
53
- expect(theme?.files[0]?.content).toContain("--radius-scale");
54
- });
55
-
56
- it("hashes match the content actually published", () => {
57
- for (const item of items) {
58
- for (const file of item.files) {
59
- expect(file.hash).toBe(hashContent(file.content));
60
- }
61
- }
62
- });
63
-
64
- it("names every registry dependency that exists", () => {
65
- const names = new Set(items.map((item) => item.name));
66
- for (const item of items) {
67
- for (const dependency of item.registryDependencies) {
68
- expect(names.has(dependency), `${item.name} depends on missing "${dependency}"`).toBe(
69
- true,
70
- );
71
- }
72
- }
73
- });
74
-
75
- it("has no dependency cycles", () => {
76
- const graph = new Map(items.map((item) => [item.name, item.registryDependencies]));
77
- const state = new Map<string, "visiting" | "done">();
78
-
79
- function visit(name: string, trail: string[]): void {
80
- const current = state.get(name);
81
- if (current === "done") return;
82
- expect(current, `cycle: ${[...trail, name].join(" → ")}`).not.toBe("visiting");
83
-
84
- state.set(name, "visiting");
85
- for (const dependency of graph.get(name) ?? []) visit(dependency, [...trail, name]);
86
- state.set(name, "done");
87
- }
88
-
89
- for (const name of graph.keys()) visit(name, []);
90
- });
91
-
92
- it("preserves directives that must stay on the first line", () => {
93
- const dialog = items.find((item) => item.name === "dialog");
94
- expect(dialog?.files[0]?.content.startsWith('"use client"')).toBe(true);
95
- });
96
-
97
- it("does not ship tests or stories", () => {
98
- for (const item of items) {
99
- for (const file of item.files) {
100
- expect(file.path).not.toMatch(/\.(test|stories)\./);
101
- }
102
- }
103
- });
104
-
105
- it("is deterministic — the same source produces identical output", () => {
106
- expect(JSON.stringify(buildRegistry())).toBe(JSON.stringify(items));
107
- });
108
- });
109
-
110
- describe("buildIndex", () => {
111
- const index = buildIndex(items);
112
-
113
- it("matches the published shape", () => {
114
- expect(() => registryIndexSchema.parse(index)).not.toThrow();
115
- });
116
-
117
- it("lists every item", () => {
118
- expect(index.items).toHaveLength(items.length);
119
- });
120
-
121
- it("records where it was generated from, not when", () => {
122
- // A timestamp would make every build a diff even when nothing changed.
123
- // Scope and package name are branding, so only the shape is asserted here.
124
- expect(index.generatedFrom).toMatch(/^@[\w-]+\/[\w-]+@\d+\.\d+\.\d+$/);
125
- expect(JSON.stringify(index)).not.toMatch(/\d{4}-\d{2}-\d{2}T/);
126
- });
127
-
128
- it("omits file contents, so the index stays small", () => {
129
- expect(JSON.stringify(index)).not.toContain("export function");
130
- });
131
- });