@open-mercato/ui 0.8.1-develop.7218.1.9f22882799 → 0.8.1-develop.7220.1.9a71dd80cf
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/build.mjs
CHANGED
|
@@ -1,22 +1,49 @@
|
|
|
1
|
-
import { writeFileSync } from 'node:fs'
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs'
|
|
2
2
|
import { dirname, join } from 'node:path'
|
|
3
3
|
import { fileURLToPath } from 'node:url'
|
|
4
4
|
import { buildPackage } from '../../scripts/build-package.mjs'
|
|
5
5
|
import { discoverResolvedIcons } from './scripts/lucideIconDiscovery.cjs'
|
|
6
|
-
import { buildLucideRegistrySource } from './scripts/lucideRegistrySource.cjs'
|
|
6
|
+
import { buildLucideRegistrySource, checkLucideRegistryDrift } from './scripts/lucideRegistrySource.cjs'
|
|
7
7
|
|
|
8
8
|
const packageDir = dirname(fileURLToPath(import.meta.url))
|
|
9
|
+
// `--check` regenerates the lucide registry in memory and fails on drift
|
|
10
|
+
// without writing or building — the CI guard mode (`yarn ui:icons:check`).
|
|
11
|
+
const checkOnly = process.argv.includes('--check')
|
|
9
12
|
|
|
10
13
|
async function generateLucideRegistry() {
|
|
11
14
|
const repoRoot = join(packageDir, '..', '..')
|
|
12
15
|
const resolved = await discoverResolvedIcons(repoRoot)
|
|
13
16
|
|
|
14
17
|
const outPath = join(packageDir, 'src/backend/icons/lucideRegistry.generated.tsx')
|
|
15
|
-
|
|
18
|
+
const source = buildLucideRegistrySource(resolved)
|
|
19
|
+
|
|
20
|
+
// `--check` makes this a drift guard instead of a writer. The committed
|
|
21
|
+
// registry is a canonical mirror of a repo-wide scan, so nothing inside
|
|
22
|
+
// `packages/ui`'s own test suite can protect it: a PR that adds
|
|
23
|
+
// `icon: 'some-lucide-name'` in another package never selects `packages/ui`
|
|
24
|
+
// under turbo's `--filter=[base]...` (ui is a dependency of those packages,
|
|
25
|
+
// not a dependent), which is exactly how #4391 drifted unnoticed. CI calls
|
|
26
|
+
// this unfiltered, mirroring `ds:tokens:check`.
|
|
27
|
+
if (checkOnly) {
|
|
28
|
+
const committed = existsSync(outPath) ? readFileSync(outPath, 'utf8') : ''
|
|
29
|
+
const drift = checkLucideRegistryDrift(committed, source, outPath)
|
|
30
|
+
if (drift.drifted) {
|
|
31
|
+
console.error(drift.message)
|
|
32
|
+
process.exit(1)
|
|
33
|
+
}
|
|
34
|
+
console.log(`Lucide registry is in sync (${resolved.length} icons).`)
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
writeFileSync(outPath, source)
|
|
16
39
|
console.log(`Generated lucide registry with ${resolved.length} icons -> ${outPath}`)
|
|
17
40
|
}
|
|
18
41
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
42
|
+
if (checkOnly) {
|
|
43
|
+
await generateLucideRegistry()
|
|
44
|
+
} else {
|
|
45
|
+
await buildPackage(packageDir, {
|
|
46
|
+
name: 'ui',
|
|
47
|
+
beforeBuild: generateLucideRegistry,
|
|
48
|
+
})
|
|
49
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/ui",
|
|
3
|
-
"version": "0.8.1-develop.
|
|
3
|
+
"version": "0.8.1-develop.7220.1.9a71dd80cf",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -155,14 +155,14 @@
|
|
|
155
155
|
"remark-gfm": "^4.0.1"
|
|
156
156
|
},
|
|
157
157
|
"peerDependencies": {
|
|
158
|
-
"@open-mercato/shared": "0.8.1-develop.
|
|
158
|
+
"@open-mercato/shared": "0.8.1-develop.7220.1.9a71dd80cf",
|
|
159
159
|
"react": ">=18.0.0",
|
|
160
160
|
"react-dom": ">=18.0.0",
|
|
161
161
|
"react-is": ">=18.0.0"
|
|
162
162
|
},
|
|
163
163
|
"devDependencies": {
|
|
164
164
|
"@figma/code-connect": "^1.3.4",
|
|
165
|
-
"@open-mercato/shared": "0.8.1-develop.
|
|
165
|
+
"@open-mercato/shared": "0.8.1-develop.7220.1.9a71dd80cf",
|
|
166
166
|
"@testing-library/dom": "^10.4.1",
|
|
167
167
|
"@testing-library/jest-dom": "^7.0.1",
|
|
168
168
|
"@testing-library/react": "^16.3.3",
|
|
@@ -130,4 +130,19 @@ function buildLucideRegistrySource(resolvedIcons) {
|
|
|
130
130
|
return normalizeSourceText(sourceFile.getFullText())
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
|
|
133
|
+
// Drift decision for the committed registry, kept here rather than inline in
|
|
134
|
+
// build.mjs so it is reachable from Jest: build.mjs's top level awaits a full
|
|
135
|
+
// package build, so nothing can import it to exercise this comparison. The
|
|
136
|
+
// caller owns reporting and the exit code; this only decides.
|
|
137
|
+
function checkLucideRegistryDrift(committedSource, generatedSource, registryPath = GENERATED_FILE_NAME) {
|
|
138
|
+
if (committedSource === generatedSource) return { drifted: false }
|
|
139
|
+
|
|
140
|
+
return {
|
|
141
|
+
drifted: true,
|
|
142
|
+
message: `Lucide icon registry is out of date: ${registryPath}\n`
|
|
143
|
+
+ 'A referenced icon name was added or removed without regenerating it.\n'
|
|
144
|
+
+ 'Run `yarn workspace @open-mercato/ui build` and commit the result.',
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
module.exports = { buildLucideRegistrySource, checkLucideRegistryDrift }
|
|
@@ -4,7 +4,7 @@ import { tmpdir } from 'node:os'
|
|
|
4
4
|
import { join } from 'node:path'
|
|
5
5
|
import { Project, ScriptKind, SyntaxKind, type ObjectLiteralExpression, type SourceFile } from 'ts-morph'
|
|
6
6
|
import { discoverResolvedIcons } from '../../../../scripts/lucideIconDiscovery.cjs'
|
|
7
|
-
import { buildLucideRegistrySource } from '../../../../scripts/lucideRegistrySource.cjs'
|
|
7
|
+
import { buildLucideRegistrySource, checkLucideRegistryDrift } from '../../../../scripts/lucideRegistrySource.cjs'
|
|
8
8
|
import jestConfig from '../../../../jest.config.cjs'
|
|
9
9
|
|
|
10
10
|
const packageDir = join(__dirname, '..', '..', '..', '..')
|
|
@@ -272,6 +272,32 @@ describe('committed lucideRegistry.generated.tsx', () => {
|
|
|
272
272
|
})
|
|
273
273
|
})
|
|
274
274
|
|
|
275
|
+
// `yarn ui:icons:check` runs this decision unfiltered in CI, where only the in-sync
|
|
276
|
+
// branch is ever exercised — every PR runs it against a registry that matches. The
|
|
277
|
+
// branch that does the work is the drifted one, so it is asserted here instead.
|
|
278
|
+
describe('checkLucideRegistryDrift', () => {
|
|
279
|
+
const source = buildLucideRegistrySource(populatedFixture)
|
|
280
|
+
|
|
281
|
+
it('reports no drift when the committed file matches the emitter', () => {
|
|
282
|
+
expect(checkLucideRegistryDrift(source, source)).toEqual({ drifted: false })
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
it('reports drift when an icon is missing from the committed file', () => {
|
|
286
|
+
const stale = buildLucideRegistrySource(populatedFixture.slice(0, -1))
|
|
287
|
+
expect(checkLucideRegistryDrift(stale, source).drifted).toBe(true)
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
it('reports drift when the committed file has never been written', () => {
|
|
291
|
+
expect(checkLucideRegistryDrift('', source).drifted).toBe(true)
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
it('names the drifted file and the command that regenerates it', () => {
|
|
295
|
+
const drift = checkLucideRegistryDrift('', source, '/repo/lucideRegistry.generated.tsx')
|
|
296
|
+
expect(drift.message).toContain('/repo/lucideRegistry.generated.tsx')
|
|
297
|
+
expect(drift.message).toContain('yarn workspace @open-mercato/ui build')
|
|
298
|
+
})
|
|
299
|
+
})
|
|
300
|
+
|
|
275
301
|
describe('jest transform scope', () => {
|
|
276
302
|
const transformPatterns = Object.keys(jestConfig.transform).map((key) => new RegExp(key))
|
|
277
303
|
|