synthesisui 0.16.1 → 0.16.2

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.
@@ -1,4 +1,4 @@
1
- import { mkdir, readFile, writeFile } from "node:fs/promises";
1
+ import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
2
2
  import { join, relative, resolve } from "node:path";
3
3
  import { syncClaudeMd } from "../claude-md.js";
4
4
  import { parseRootTokens } from "../doctor/tokens.js";
@@ -75,6 +75,34 @@ function guessSlug(tokens, pkgName) {
75
75
  .replace(/^-|-$/g, "")
76
76
  .toLowerCase() || "my-system");
77
77
  }
78
+ /**
79
+ * A system WE installed, if there is one.
80
+ *
81
+ * Run inside a repo already carrying Moments - 158 tokens, 93% coverage - adopt
82
+ * announced "found no custom properties … if you do not have a system yet,
83
+ * start from one" (27/07). Telling somebody with a design system that they have
84
+ * none is the exact dead end this command was written to avoid: our own tokens
85
+ * live under `_synthesisui/`, which the walk skips, so it looked and found
86
+ * nothing and drew the wrong conclusion from it.
87
+ */
88
+ async function installedSystems(root) {
89
+ const dir = join(root, "_synthesisui", "ds");
90
+ const slugs = [];
91
+ for (const e of await readdir(dir, { withFileTypes: true }).catch(() => [])) {
92
+ if (!e.isDirectory())
93
+ continue;
94
+ const raw = await readFile(join(dir, e.name, ".lock"), "utf8").catch(() => "");
95
+ try {
96
+ const lock = JSON.parse(raw);
97
+ if (!lock.adopted)
98
+ slugs.push(lock.name ?? e.name);
99
+ }
100
+ catch {
101
+ // no readable lock - not something we put there
102
+ }
103
+ }
104
+ return slugs;
105
+ }
78
106
  async function findTokens(root, only) {
79
107
  let files = 0;
80
108
  const from = [];
@@ -146,6 +174,14 @@ export async function adopt(opts) {
146
174
  const found = await findTokens(root, opts.tokens);
147
175
  console.log(section("Adopt"));
148
176
  if (found.tokens.size === 0) {
177
+ const already = await installedSystems(root);
178
+ if (already.length > 0) {
179
+ console.log(body(`${already.join(", ")} ${already.length === 1 ? "is" : "are"} already installed here, and adopt is for a system we did not install.`));
180
+ console.log("");
181
+ console.log(body("Nothing to do. To see how the code is holding up:"));
182
+ console.log(snippet(["npx synthesisui@latest doctor"]));
183
+ return;
184
+ }
149
185
  // Never "failed to adopt". Always: what was looked for, where, and the
150
186
  // next thing to type. Being stuck with no move is the worst outcome.
151
187
  console.log(body(`Looked in ${SCOPE_HINT} across ${found.files} stylesheet${found.files === 1 ? "" : "s"} and found no custom properties.`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "synthesisui",
3
- "version": "0.16.1",
3
+ "version": "0.16.2",
4
4
  "description": "Bring SynthesisUI design systems into any project - tokens, typed components, whole pages and an agent-ready CLAUDE.md manifest.",
5
5
  "type": "module",
6
6
  "bin": {