@moontra/moonui 6.19.1 → 6.20.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moontra/moonui",
3
- "version": "6.19.1",
3
+ "version": "6.20.0",
4
4
  "description": "Premium React component library with modern design and customization",
5
5
  "author": "MoonUI",
6
6
  "license": "MIT",
@@ -15,6 +15,8 @@
15
15
  "main": "dist/index.js",
16
16
  "module": "dist/index.mjs",
17
17
  "types": "dist/index.d.ts",
18
+ "unpkg": "dist/cdn/moonui.global.js",
19
+ "jsdelivr": "dist/cdn/moonui.global.js",
18
20
  "sideEffects": [
19
21
  "**/*.css"
20
22
  ],
@@ -57,9 +59,13 @@
57
59
  ],
58
60
  "scripts": {
59
61
  "dev": "tsup src/index.tsx --format esm,cjs --dts --watch --sourcemap",
60
- "build": "npm run build:js && npm run build:dts && node scripts/postbuild.js",
62
+ "build": "npm run build:js && npm run build:dts && node scripts/postbuild.js && npm run build:cdn",
61
63
  "build:js": "tsup",
62
64
  "build:dts": "tsup --dts-only",
65
+ "build:cdn": "npm run build:cdn:js && npm run build:cdn:css",
66
+ "build:cdn:js": "tsup --config tsup.cdn.config.ts",
67
+ "build:cdn:css": "tailwindcss -c tailwind.cdn.config.js -i src/styles/cdn.css -o dist/cdn/moonui.css --minify",
68
+ "verify:cdn": "node scripts/cdn/verify-cdn.mjs",
63
69
  "lint": "eslint \"src/**/*.{ts,tsx}\" --fix",
64
70
  "clean": "rm -rf dist",
65
71
  "prepublishOnly": "npm run clean && npm run build",
@@ -0,0 +1,178 @@
1
+ /**
2
+ * CDN YUZEYI GUARD'I — @moontra/moonui. Issue #410 (onceki hali: #399).
3
+ *
4
+ * ─── BU DOSYA NEDEN VAR: #399'UN HIKAYESI ────────────────────────────────────
5
+ * `tsup.config.ts` ikinci bir tanimda `format: ["iife"]` + `globalName: "MoonUI"`
6
+ * ilan ediyordu, ama `package.json`'daki `build:js` tsup'i CLI argumaniyla
7
+ * cagiriyordu (`tsup src/... --format esm,cjs`). tsup'ta CLI argumani config'i
8
+ * EZER → IIFE hic uretilmedi; `.global.js` ADIYLA bir ES modulu yayimlandi.
9
+ * Dosya adi IIFE vaat ettigi icin hata SESSIZDI: `window.MoonUI` hicbir surumde
10
+ * olusmadi, buna ragmen her tarball 4.7 MB olu `.global.*` artefakti tasidi.
11
+ * #399 o yuzden yuzeyi tamamen kaldirdi ve bu dosya "kaldirildi" kararini kilitledi.
12
+ *
13
+ * ─── SIMDI NE DEGISTI (#410) ─────────────────────────────────────────────────
14
+ * Yuzey CALISIR HALDE geri geldi: React artik bundle'a girmiyor (cift-React
15
+ * cokmesinin kok nedeniydi — docs/cdn-destegi-plani.md §2.2), CDN icin ayri bir
16
+ * CSS artefakti uretiliyor ve React 19 icin ESM cikti da var (React 19 UMD
17
+ * yayimlamiyor, IIFE tek basina yetmez).
18
+ *
19
+ * Dosya SILINMEDI, YENIDEN YAZILDI: kilitlenen sey "yuzey yok" degil, artik
20
+ * "yuzey var ve GERCEKTEN calisir sekilde var". #399'un dersi aynen gecerli —
21
+ * SESSIZ KIRILMA EN PAHALI KIRILMADIR — bu yuzden guard uc katmani birden tutar:
22
+ * 1. build config (ne ilan ediliyor)
23
+ * 2. paket metadata'si (unpkg/jsdelivr NEREYI gosteriyor)
24
+ * 3. uretilmis dist (icerik gercekten IIFE mi, React sizmis mi, CSS token'li mi)
25
+ *
26
+ * ⚠️ BU GUARD'IN YAKALAYAMADIGI TEK SEY: "component tarayicida calisiyor mu".
27
+ * Onu `scripts/cdn/verify-cdn.mjs` gercek tarayicida olcer (npm run verify:cdn) —
28
+ * cift-React cokmesi ancak calisma zamaninda gorunur.
29
+ */
30
+ import * as fs from 'fs';
31
+ import * as path from 'path';
32
+
33
+ const PACKAGE_ROOT = path.resolve(__dirname, '../..');
34
+ const TSUP_CONFIG = path.join(PACKAGE_ROOT, 'tsup.config.ts');
35
+ const TSUP_CDN_CONFIG = path.join(PACKAGE_ROOT, 'tsup.cdn.config.ts');
36
+ const PACKAGE_JSON = path.join(PACKAGE_ROOT, 'package.json');
37
+ const DIST_CDN = path.join(PACKAGE_ROOT, 'dist', 'cdn');
38
+
39
+ const IIFE_BUNDLE = path.join(DIST_CDN, 'moonui.global.js');
40
+ const ESM_BUNDLE = path.join(DIST_CDN, 'moonui.esm.js');
41
+ const CDN_CSS = path.join(DIST_CDN, 'moonui.css');
42
+
43
+ /** Yorumlari ayikla: karar gerekcesi metinlerinde "iife"/".global.js" geciyor. */
44
+ function stripComments(source: string): string {
45
+ return source.replace(/\/\/.*$/gm, '').replace(/\/\*[\s\S]*?\*\//g, '');
46
+ }
47
+
48
+ const pkg: Record<string, unknown> = JSON.parse(fs.readFileSync(PACKAGE_JSON, 'utf8'));
49
+ const scripts = pkg.scripts as Record<string, string>;
50
+
51
+ describe('CDN yuzeyi — build config (#410)', () => {
52
+ it('CDN tanimi ANA config\'te DEGIL, ayri dosyada', () => {
53
+ // Gerekce: `build:dts` → `tsup --dts-only` bayragi TUM tanimlara uygulanir.
54
+ // CDN tanimi ana config'te olsaydi dts uretimiyle etkilesirdi.
55
+ const main = stripComments(fs.readFileSync(TSUP_CONFIG, 'utf8'));
56
+ expect(main).not.toMatch(/format\s*:\s*\[[^\]]*['"]iife['"]/);
57
+ expect(main).not.toMatch(/globalName\s*:/);
58
+ expect(fs.existsSync(TSUP_CDN_CONFIG)).toBe(true);
59
+ });
60
+
61
+ it('CDN config\'i HEM IIFE HEM ESM uretiyor', () => {
62
+ const cdn = stripComments(fs.readFileSync(TSUP_CDN_CONFIG, 'utf8'));
63
+ expect(cdn).toMatch(/format\s*:\s*\[\s*['"]iife['"]\s*\]/);
64
+ expect(cdn).toMatch(/format\s*:\s*\[\s*['"]esm['"]\s*\]/);
65
+ // ESM sarti pazarlik konusu degil: React 19 UMD yayimlamiyor, IIFE
66
+ // (window.React) React 19 tuketicisine hitap etmiyor.
67
+ expect(cdn).toMatch(/globalName\s*:\s*['"]MoonUI['"]/);
68
+ });
69
+
70
+ it('React\'i disari alan plugin\'ler her iki tanimda da bagli', () => {
71
+ const cdn = stripComments(fs.readFileSync(TSUP_CDN_CONFIG, 'utf8'));
72
+ expect(cdn).toMatch(/reactGlobalExternals\(/);
73
+ expect(cdn).toMatch(/bareReactExternals\(/);
74
+ for (const plugin of ['react-global-externals.mjs', 'bare-react-externals.mjs']) {
75
+ expect(fs.existsSync(path.join(PACKAGE_ROOT, 'scripts', 'cdn', plugin))).toBe(true);
76
+ }
77
+ });
78
+
79
+ /**
80
+ * #399'un kok nedeni: CLI argumani tsup config'ini ezer. Bu iki script
81
+ * entry/format'i CLI'dan gecmedigi surece config tek kaynak kalir.
82
+ */
83
+ it.each(['build:js', 'build:dts'])('%s tsup config\'ini CLI argumaniyla ezmiyor', (script) => {
84
+ expect(scripts[script]).toBeDefined();
85
+ expect(scripts[script]).not.toMatch(/--format/);
86
+ expect(scripts[script]).not.toMatch(/\bsrc\//);
87
+ });
88
+ });
89
+
90
+ describe('CDN yuzeyi — paket metadata (#410)', () => {
91
+ it.each(['unpkg', 'jsdelivr'])('%s alani var ve dist/cdn/moonui.global.js\'i gosteriyor', (field) => {
92
+ expect(pkg[field]).toBe('dist/cdn/moonui.global.js');
93
+ });
94
+
95
+ it('unpkg/jsdelivr DISKTE VAR OLAN bir dosyayi gosteriyor', () => {
96
+ // #399'daki hatanin metadata karsiligi: alanlar hicbir zaman uretilmeyen
97
+ // bir dosyaya bakiyordu. Build yapilmamissa atlanir (asil kapi yukarisi).
98
+ if (!fs.existsSync(DIST_CDN)) return;
99
+ for (const field of ['unpkg', 'jsdelivr'] as const) {
100
+ expect(fs.existsSync(path.join(PACKAGE_ROOT, pkg[field] as string))).toBe(true);
101
+ }
102
+ });
103
+
104
+ it('build zinciri CDN adimini iceriyor ve postbuild\'den SONRA calisiyor', () => {
105
+ // Sira onemli: `scripts/postbuild.js` dist'teki HER bundle'in basina
106
+ // 'use client' koyar. CDN cikti(lari) ondan SONRA uretilmeli, yoksa
107
+ // tarayiciya anlamsiz bir direktif gider.
108
+ const build = scripts.build;
109
+ expect(build).toContain('build:cdn');
110
+ expect(build.indexOf('postbuild.js')).toBeLessThan(build.indexOf('build:cdn'));
111
+ expect(scripts['build:cdn']).toBeDefined();
112
+ expect(scripts['build:cdn:css']).toBeDefined();
113
+ });
114
+
115
+ it('files alani dist/** uzerinden CDN ciktisini kapsiyor', () => {
116
+ expect(pkg.files as string[]).toContain('dist/**');
117
+ });
118
+ });
119
+
120
+ // ─── dist katmani: build yapilmissa kosar, asil kapi yukaridaki iki katmandir ──
121
+ const distBuilt = fs.existsSync(IIFE_BUNDLE) && fs.existsSync(ESM_BUNDLE) && fs.existsSync(CDN_CSS);
122
+ const describeDist = distBuilt ? describe : describe.skip;
123
+
124
+ describeDist('CDN yuzeyi — uretilmis dist (#410)', () => {
125
+ let iife = '';
126
+ let esm = '';
127
+ let css = '';
128
+ beforeAll(() => {
129
+ iife = fs.readFileSync(IIFE_BUNDLE, 'utf8');
130
+ esm = fs.readFileSync(ESM_BUNDLE, 'utf8');
131
+ css = fs.readFileSync(CDN_CSS, 'utf8');
132
+ });
133
+
134
+ it('`.global.js` GERCEKTEN IIFE — #399\'da adi IIFE, icerigi ESM\'di', () => {
135
+ expect(iife).toMatch(/var MoonUI\s*=\s*\(\(\)\s*=>/);
136
+ // ESM izleri olmamali: top-level import/export bir IIFE'de bulunamaz.
137
+ expect(iife).not.toMatch(/^\s*import\s/m);
138
+ expect(iife).not.toMatch(/^\s*export\s*\{/m);
139
+ });
140
+
141
+ it('`.esm.js` gercekten ESM ve React\'i CIPLAK import olarak birakiyor', () => {
142
+ expect(esm).toMatch(/from\s*["']react["']/);
143
+ expect(esm).toMatch(/export\s*\{/);
144
+ expect(esm).not.toMatch(/var MoonUI\s*=\s*\(\(\)\s*=>/);
145
+ });
146
+
147
+ it.each([
148
+ ['IIFE', () => iife],
149
+ ['ESM', () => esm],
150
+ ])('%s bundle\'inda React SIZMAMIS (cift-React cokmesinin kok nedeni)', (_label, read) => {
151
+ const source = read();
152
+ expect(source).not.toContain('Minified React error');
153
+ expect(source).not.toContain('react-dom.production');
154
+ });
155
+
156
+ it('IIFE React\'i sayfanin global\'inden okuyor (shim yerinde)', () => {
157
+ expect(iife).toContain('globalThis.React');
158
+ });
159
+
160
+ it('CDN bundle\'larina \'use client\' EKLENMEMIS', () => {
161
+ // Tarayiciya giden bir dosyada anlami yok; postbuild sirasi bunu garanti eder.
162
+ for (const source of [iife, esm]) {
163
+ expect(source.slice(0, 200)).not.toMatch(/['"]use client['"]/);
164
+ }
165
+ });
166
+
167
+ it('CDN CSS\'i TOKEN iceriyor — sadece utility degil', () => {
168
+ // Plan §2.3'teki tuzak: `@import` sirasi yanlis olursa postcss-import
169
+ // token dosyalarini SESSIZCE duser ve tum renkler bos kalir.
170
+ expect(css).toMatch(/--primary:\s*[\d.]+/);
171
+ expect(css).toMatch(/--background:\s*[\d.]+/);
172
+ });
173
+
174
+ it('CDN CSS\'i component utility\'lerini iceriyor', () => {
175
+ expect(css).toContain('.bg-primary');
176
+ expect(css).toContain('.border-border');
177
+ });
178
+ });