@pure-ds/core 0.4.37 โ†’ 0.5.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.
Files changed (146) hide show
  1. package/dist/types/pds.d.ts +34 -11
  2. package/dist/types/public/assets/auto-definer-XWHRBQPU.d.ts +9 -0
  3. package/dist/types/public/assets/auto-definer-XWHRBQPU.d.ts.map +1 -0
  4. package/dist/types/public/assets/chunk-746HIXIK.d.ts +52 -0
  5. package/dist/types/public/assets/chunk-746HIXIK.d.ts.map +1 -0
  6. package/dist/types/public/assets/chunk-APJV5T3J.d.ts +106 -0
  7. package/dist/types/public/assets/chunk-APJV5T3J.d.ts.map +1 -0
  8. package/dist/types/public/assets/chunk-BEPKFFM7.d.ts +398 -0
  9. package/dist/types/public/assets/chunk-BEPKFFM7.d.ts.map +1 -0
  10. package/dist/types/public/assets/chunk-ISS7UH5H.d.ts +2424 -0
  11. package/dist/types/public/assets/chunk-ISS7UH5H.d.ts.map +1 -0
  12. package/dist/types/public/assets/chunk-RUPLQUDG.d.ts +582 -0
  13. package/dist/types/public/assets/chunk-RUPLQUDG.d.ts.map +1 -0
  14. package/dist/types/public/assets/chunk-USML4NYF.d.ts +18 -0
  15. package/dist/types/public/assets/chunk-USML4NYF.d.ts.map +1 -0
  16. package/dist/types/public/assets/chunk-Z47A3HLT.d.ts +3 -0
  17. package/dist/types/public/assets/chunk-Z47A3HLT.d.ts.map +1 -0
  18. package/dist/types/public/assets/js/auto-definer-HZLD2XF4.d.ts +9 -0
  19. package/dist/types/public/assets/js/auto-definer-HZLD2XF4.d.ts.map +1 -0
  20. package/dist/types/public/assets/js/chunk-6A6DFAIG.d.ts +88 -0
  21. package/dist/types/public/assets/js/chunk-6A6DFAIG.d.ts.map +1 -0
  22. package/dist/types/public/assets/js/chunk-746HIXIK.d.ts +52 -0
  23. package/dist/types/public/assets/js/chunk-746HIXIK.d.ts.map +1 -0
  24. package/dist/types/public/assets/js/chunk-A3TZGIYX.d.ts +4 -0
  25. package/dist/types/public/assets/js/chunk-A3TZGIYX.d.ts.map +1 -0
  26. package/dist/types/public/assets/js/chunk-BEPKFFM7.d.ts +398 -0
  27. package/dist/types/public/assets/js/chunk-BEPKFFM7.d.ts.map +1 -0
  28. package/dist/types/public/assets/js/chunk-OTTRJ5MB.d.ts +1695 -0
  29. package/dist/types/public/assets/js/chunk-OTTRJ5MB.d.ts.map +1 -0
  30. package/dist/types/public/assets/js/chunk-RBPKHG76.d.ts +747 -0
  31. package/dist/types/public/assets/js/chunk-RBPKHG76.d.ts.map +1 -0
  32. package/dist/types/public/assets/js/chunk-RUPLQUDG.d.ts +582 -0
  33. package/dist/types/public/assets/js/chunk-RUPLQUDG.d.ts.map +1 -0
  34. package/dist/types/public/assets/js/chunk-SMD2R3CX.d.ts +68 -0
  35. package/dist/types/public/assets/js/chunk-SMD2R3CX.d.ts.map +1 -0
  36. package/dist/types/public/assets/js/chunk-Y73DA2D5.d.ts +15 -0
  37. package/dist/types/public/assets/js/chunk-Y73DA2D5.d.ts.map +1 -0
  38. package/dist/types/public/assets/js/chunks/auto-definer-X7MSXKTU.d.ts +9 -0
  39. package/dist/types/public/assets/js/chunks/auto-definer-X7MSXKTU.d.ts.map +1 -0
  40. package/dist/types/public/assets/js/chunks/chunk-7BDQH5CT.d.ts +485 -0
  41. package/dist/types/public/assets/js/chunks/chunk-7BDQH5CT.d.ts.map +1 -0
  42. package/dist/types/public/assets/js/chunks/chunk-MWB3S7NG.d.ts +3 -0
  43. package/dist/types/public/assets/js/chunks/chunk-MWB3S7NG.d.ts.map +1 -0
  44. package/dist/types/public/assets/js/chunks/chunk-WIMLORAU.d.ts +5 -0
  45. package/dist/types/public/assets/js/chunks/chunk-WIMLORAU.d.ts.map +1 -0
  46. package/dist/types/public/assets/js/chunks/chunk-WN4Y2ELN.d.ts +833 -0
  47. package/dist/types/public/assets/js/chunks/chunk-WN4Y2ELN.d.ts.map +1 -0
  48. package/dist/types/public/assets/js/chunks/chunk-XQOUIBLO.d.ts +1687 -0
  49. package/dist/types/public/assets/js/chunks/chunk-XQOUIBLO.d.ts.map +1 -0
  50. package/dist/types/public/assets/js/chunks/font-loader-VN5SRNOD.d.ts +5 -0
  51. package/dist/types/public/assets/js/chunks/font-loader-VN5SRNOD.d.ts.map +1 -0
  52. package/dist/types/public/assets/js/chunks/pds-live-validation-BQPWN5JG.d.ts +38 -0
  53. package/dist/types/public/assets/js/chunks/pds-live-validation-BQPWN5JG.d.ts.map +1 -0
  54. package/dist/types/public/assets/js/common-WIAC4WAJ.d.ts +4 -0
  55. package/dist/types/public/assets/js/common-WIAC4WAJ.d.ts.map +1 -0
  56. package/dist/types/public/assets/js/pds-config-WEBAXXSM.d.ts +4 -0
  57. package/dist/types/public/assets/js/pds-config-WEBAXXSM.d.ts.map +1 -0
  58. package/dist/types/public/assets/js/pds-core/pds-generator.d.ts +700 -0
  59. package/dist/types/public/assets/js/pds-core/pds-generator.d.ts.map +1 -0
  60. package/dist/types/public/assets/js/pds-core/pds-utilities.d.ts +27 -0
  61. package/dist/types/public/assets/js/pds-core/pds-utilities.d.ts.map +1 -0
  62. package/dist/types/public/assets/js/pds-enums-DCBZHS64.d.ts +3 -0
  63. package/dist/types/public/assets/js/pds-enums-DCBZHS64.d.ts.map +1 -0
  64. package/dist/types/public/assets/js/pds-gen.d.ts +106 -0
  65. package/dist/types/public/assets/js/pds-gen.d.ts.map +1 -0
  66. package/dist/types/public/assets/js/pds-live.d.ts +11 -0
  67. package/dist/types/public/assets/js/pds-live.d.ts.map +1 -0
  68. package/dist/types/public/assets/js/pds-manager.d.ts +1047 -0
  69. package/dist/types/public/assets/js/pds-manager.d.ts.map +1 -0
  70. package/dist/types/public/assets/js/pds-ontology-2DICJXHO.d.ts +9 -0
  71. package/dist/types/public/assets/js/pds-ontology-2DICJXHO.d.ts.map +1 -0
  72. package/dist/types/public/assets/js/pds-query-B54LBKKR.d.ts +70 -0
  73. package/dist/types/public/assets/js/pds-query-B54LBKKR.d.ts.map +1 -0
  74. package/dist/types/public/assets/js/pds.d.ts +1 -18
  75. package/dist/types/public/assets/js/pds.d.ts.map +1 -1
  76. package/dist/types/public/assets/pds-ontology-ZO6TJHO3.d.ts +9 -0
  77. package/dist/types/public/assets/pds-ontology-ZO6TJHO3.d.ts.map +1 -0
  78. package/dist/types/src/js/common/pds-core/pds-config.d.ts +757 -0
  79. package/dist/types/src/js/common/pds-core/pds-config.d.ts.map +1 -0
  80. package/dist/types/src/js/common/pds-core/pds-enhancers.d.ts +28 -0
  81. package/dist/types/src/js/common/pds-core/pds-enhancers.d.ts.map +1 -0
  82. package/dist/types/src/js/common/pds-core/pds-enums.d.ts +87 -0
  83. package/dist/types/src/js/common/pds-core/pds-enums.d.ts.map +1 -0
  84. package/dist/types/src/js/common/pds-core/pds-generator.d.ts +700 -0
  85. package/dist/types/src/js/common/pds-core/pds-generator.d.ts.map +1 -0
  86. package/dist/types/src/js/common/pds-core/pds-ontology.d.ts +380 -0
  87. package/dist/types/src/js/common/pds-core/pds-ontology.d.ts.map +1 -0
  88. package/dist/types/src/js/common/pds-core/pds-paths.d.ts +37 -0
  89. package/dist/types/src/js/common/pds-core/pds-paths.d.ts.map +1 -0
  90. package/dist/types/src/js/common/pds-core/pds-query.d.ts +102 -0
  91. package/dist/types/src/js/common/pds-core/pds-query.d.ts.map +1 -0
  92. package/dist/types/src/js/common/pds-core/pds-registry.d.ts +35 -0
  93. package/dist/types/src/js/common/pds-core/pds-registry.d.ts.map +1 -0
  94. package/dist/types/src/js/common/pds-core/pds-utilities.d.ts +27 -0
  95. package/dist/types/src/js/common/pds-core/pds-utilities.d.ts.map +1 -0
  96. package/dist/types/src/js/pds-core/pds-generator.d.ts +38 -46
  97. package/dist/types/src/js/pds-core/pds-generator.d.ts.map +1 -1
  98. package/dist/types/src/js/pds-core/pds-live.d.ts +39 -0
  99. package/dist/types/src/js/pds-core/pds-live.d.ts.map +1 -0
  100. package/dist/types/src/js/pds-core/pds-runtime.d.ts +39 -0
  101. package/dist/types/src/js/pds-core/pds-runtime.d.ts.map +1 -0
  102. package/dist/types/src/js/pds-core/pds-start-helpers.d.ts +60 -0
  103. package/dist/types/src/js/pds-core/pds-start-helpers.d.ts.map +1 -0
  104. package/dist/types/src/js/pds-core/pds-utilities.d.ts +27 -0
  105. package/dist/types/src/js/pds-core/pds-utilities.d.ts.map +1 -0
  106. package/dist/types/src/js/pds-gen.d.ts +48 -0
  107. package/dist/types/src/js/pds-gen.d.ts.map +1 -0
  108. package/dist/types/src/js/pds-live-runtime.d.ts +7 -0
  109. package/dist/types/src/js/pds-live-runtime.d.ts.map +1 -0
  110. package/dist/types/src/js/pds-live-validation.d.ts +44 -0
  111. package/dist/types/src/js/pds-live-validation.d.ts.map +1 -0
  112. package/dist/types/src/js/pds-live.d.ts +11 -0
  113. package/dist/types/src/js/pds-live.d.ts.map +1 -0
  114. package/dist/types/src/js/pds-manager.d.ts +2 -0
  115. package/dist/types/src/js/pds-manager.d.ts.map +1 -0
  116. package/dist/types/src/js/pds.d.ts +6 -33
  117. package/dist/types/src/js/pds.d.ts.map +1 -1
  118. package/package.json +11 -12
  119. package/packages/pds-cli/bin/{generate-css-data.mjs โ†’ generate-css-data.js} +563 -563
  120. package/packages/pds-cli/bin/{generate-manifest.mjs โ†’ generate-manifest.js} +352 -352
  121. package/packages/pds-cli/bin/{pds-build-icons.mjs โ†’ pds-build-icons.js} +152 -152
  122. package/packages/pds-cli/bin/{pds-dx.mjs โ†’ pds-dx.js} +114 -114
  123. package/packages/pds-cli/bin/{pds-init-config.mjs โ†’ pds-init-config.js} +34 -34
  124. package/packages/pds-cli/bin/{pds-setup-copilot.mjs โ†’ pds-setup-copilot.js} +106 -106
  125. package/packages/pds-cli/bin/{pds-static.mjs โ†’ pds-static.js} +597 -581
  126. package/packages/pds-cli/bin/{pds.mjs โ†’ pds.js} +127 -127
  127. package/packages/pds-cli/bin/postinstall.mjs +522 -563
  128. package/packages/pds-cli/bin/{sync-assets.mjs โ†’ sync-assets.js} +251 -251
  129. package/packages/pds-cli/lib/{asset-roots.mjs โ†’ asset-roots.js} +47 -47
  130. package/packages/pds-cli/lib/{fs-writer.mjs โ†’ fs-writer.js} +75 -75
  131. package/public/assets/js/app.js +95 -118
  132. package/public/assets/js/pds-manager.js +3251 -0
  133. package/public/assets/js/pds.js +10 -3201
  134. package/readme.md +2014 -2016
  135. package/src/js/pds-core/pds-enhancers.js +518 -518
  136. package/src/js/pds-core/pds-enums.js +86 -86
  137. package/src/js/pds-core/pds-generator.js +255 -185
  138. package/src/js/pds-core/pds-live.js +434 -0
  139. package/src/js/pds-core/pds-paths.js +109 -109
  140. package/src/js/pds-core/pds-registry.js +79 -79
  141. package/src/js/pds-core/pds-runtime.js +184 -0
  142. package/src/js/pds-core/pds-start-helpers.js +405 -0
  143. package/src/js/pds.d.ts +34 -11
  144. package/src/js/pds.js +43 -1182
  145. package/getting-started.md +0 -626
  146. package/src/js/pds-core/pds.d.ts +0 -129
@@ -1,564 +1,523 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * NPM postinstall script for @pure-ds/core
5
- * Automatically copies PDS assets to the consuming app's web root
6
- */
7
-
8
- import { readFile, writeFile, mkdir, copyFile, readdir, stat, access, unlink } from 'fs/promises';
9
- import { readFileSync } from 'fs';
10
- import { createHash } from 'crypto';
11
- import path from 'path';
12
- import { fileURLToPath, pathToFileURL } from 'url';
13
-
14
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
15
- const repoRoot = path.resolve(__dirname, '../../../');
16
- const isWin = process.platform === 'win32';
17
- const normalizePath = (p) => {
18
- if (!p) return '';
19
- const resolved = path.resolve(p).replace(/[\\/]+$/, '');
20
- return isWin ? resolved.toLowerCase() : resolved;
21
- };
22
-
23
- /**
24
- * Check if we're installing within the @pure-ds/core repo itself (not a consumer)
25
- */
26
- function isInstallingWithinPureDsRepo() {
27
- try {
28
- const cwd = process.cwd();
29
- const initCwd = process.env.INIT_CWD || cwd;
30
-
31
- // Check if the INIT_CWD has package.json with name "@pure-ds/core"
32
- // This is more reliable than path comparison since repoRoot
33
- // points to node_modules/@pure-ds/core when installed as a dependency
34
- try {
35
- const pkgPath = path.join(initCwd, 'package.json');
36
- const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
37
- return pkg.name === '@pure-ds/core' || pkg.name === 'pure-ds';
38
- } catch {
39
- return false;
40
- }
41
- } catch (err) {
42
- console.log('โš ๏ธ Error checking repo location:', err.message);
43
- return false;
44
- }
45
- }
46
-
47
- function isNpmLinkInvocation() {
48
- const truthy = (value) => {
49
- if (value === undefined || value === null) return false;
50
- const normalized = String(value).toLowerCase();
51
- return normalized === 'true' || normalized === '1';
52
- };
53
-
54
- if (truthy(process.env.npm_config_link)) return true;
55
- if ((process.env.npm_command || '').toLowerCase() === 'link') return true;
56
-
57
- try {
58
- const argvRaw = process.env.npm_config_argv;
59
- if (!argvRaw) return false;
60
- const argv = JSON.parse(argvRaw);
61
- const orig = argv && (argv.original || argv.cooked || []);
62
- if (!Array.isArray(orig)) return false;
63
- return orig.includes('link');
64
- } catch {
65
- return false;
66
- }
67
- }
68
-
69
- function isLinkedPackagePath(p) {
70
- return !/[\\/]+node_modules[\\/]+/i.test(p);
71
- }
72
-
73
- function isGlobalInstall() {
74
- const value = process.env.npm_config_global;
75
- if (!value) return false;
76
- const normalized = String(value).toLowerCase();
77
- return normalized === 'true' || normalized === '1';
78
- }
79
-
80
- /**
81
- * Find the consumer app root (directory containing the consumer's package.json)
82
- * Prefer INIT_CWD (npm sets this to the original cwd) and fallback by walking up from the package dir
83
- */
84
- async function findConsumerRoot() {
85
- const tryPaths = [];
86
- if (process.env.INIT_CWD) tryPaths.push(process.env.INIT_CWD);
87
- // Walk up from the package dir until we exit node_modules
88
- let dir = repoRoot;
89
- while (dir && path.basename(dir) !== path.dirname(dir)) {
90
- if (path.basename(dir) === 'node_modules') {
91
- const candidate = path.dirname(dir);
92
- tryPaths.push(candidate);
93
- break;
94
- }
95
- dir = path.dirname(dir);
96
- }
97
-
98
- for (const p of tryPaths) {
99
- try {
100
- const pkgPath = path.join(p, 'package.json');
101
- const pkg = JSON.parse(await readFile(pkgPath, 'utf8'));
102
- if (pkg && pkg.name && pkg.name !== 'pure-ds') {
103
- return p;
104
- }
105
- } catch {}
106
- }
107
-
108
- // Final fallback: INIT_CWD or current working dir
109
- return process.env.INIT_CWD || process.cwd();
110
- }
111
-
112
- /**
113
- * Ensure consumer package.json contains a handy export script
114
- */
115
- async function ensureExportScript(consumerRoot) {
116
- try {
117
- const consumerPkgPath = path.join(consumerRoot, 'package.json');
118
- const consumerPkgRaw = await readFile(consumerPkgPath, 'utf8');
119
- const consumerPkg = JSON.parse(consumerPkgRaw);
120
-
121
- consumerPkg.scripts = consumerPkg.scripts || {};
122
-
123
- const desiredScriptName = 'pds:export';
124
- const desiredScriptCmd = 'pds-export';
125
-
126
- if (!consumerPkg.scripts[desiredScriptName]) {
127
- consumerPkg.scripts[desiredScriptName] = desiredScriptCmd;
128
- await writeFile(consumerPkgPath, JSON.stringify(consumerPkg, null, 2) + '\n');
129
- console.log(`๐Ÿงฉ Added "${desiredScriptName}" script to consumer package.json`);
130
- } else {
131
- console.log(`๐Ÿ”ง Script "${desiredScriptName}" already present in consumer package.json`);
132
- }
133
- } catch (e) {
134
- console.warn('โš ๏ธ Could not ensure pds:export script in consumer package.json:', e.message);
135
- }
136
- }
137
-
138
- /**
139
- * Create default pds.config.js if it doesn't exist
140
- * @param {string} consumerRoot - The root directory to create the config in
141
- * @param {boolean} force - If true, overwrite existing config
142
- */
143
- async function ensurePdsConfig(consumerRoot, force = false) {
144
- try {
145
- const configPath = path.join(consumerRoot, 'pds.config.js');
146
-
147
- // Check if config already exists
148
- try {
149
- await access(configPath);
150
- if (!force) {
151
- console.log('๐Ÿ“ pds.config.js already exists, skipping...');
152
- return;
153
- }
154
- console.log('๐Ÿ“ Overwriting existing pds.config.js...');
155
- } catch {
156
- // File doesn't exist, create it
157
- }
158
-
159
- const defaultConfig = `export const config = {
160
- mode: "live",
161
- preset: "default",
162
-
163
- // Uncomment to override preset design tokens:
164
- // design: {
165
- // colors: {
166
- // primary: '#007acc',
167
- // secondary: '#5c2d91',
168
- // accent: '#ec4899'
169
- // },
170
- // typography: {
171
- // fontFamilyHeadings: 'Inter, sans-serif',
172
- // fontFamilyBody: 'Inter, sans-serif',
173
- // baseFontSize: 16,
174
- // fontScale: 1.25
175
- // },
176
- // spatialRhythm: {
177
- // baseUnit: 8,
178
- // scaleRatio: 1.5
179
- // }
180
- // },
181
-
182
- // Uncomment to add custom progressive enhancers:
183
- // enhancers: [
184
- // {
185
- // selector: '[data-tooltip]',
186
- // description: 'Adds tooltip on hover',
187
- // run: (element) => {
188
- // const text = element.dataset.tooltip;
189
- // element.addEventListener('mouseenter', () => {
190
- // // Show tooltip implementation
191
- // });
192
- // }
193
- // }
194
- // ],
195
-
196
- // Uncomment to customize lazy-loaded web components:
197
- // autoDefine: {
198
- // baseURL: '/pds/components/',
199
- // predefine: ['pds-icon', 'pds-drawer', 'pds-toaster'],
200
- //
201
- // // Custom component paths
202
- // mapper: (tag) => {
203
- // if (tag.startsWith('my-')) {
204
- // return \`/components/\${tag}.js\`;
205
- // }
206
- // // Return nothing to use PDS default mapping
207
- // }
208
- // }
209
- };
210
- `;
211
-
212
- await writeFile(configPath, defaultConfig, 'utf8');
213
- console.log('๐Ÿ“ Created default pds.config.js');
214
- } catch (e) {
215
- console.warn('โš ๏ธ Could not create pds.config.js:', e.message);
216
- }
217
- }
218
-
219
- /**
220
- * Copy PDS Copilot instructions to consumer's .github folder
221
- */
222
- async function copyCopilotInstructions(consumerRoot) {
223
- try {
224
- const sourceFile = path.join(repoRoot, '.github', 'copilot-instructions.md');
225
- const targetDir = path.join(consumerRoot, '.github');
226
- const targetFile = path.join(targetDir, 'copilot-instructions.md');
227
-
228
- // Create .github directory if it doesn't exist
229
- await mkdir(targetDir, { recursive: true });
230
-
231
- // Check if file already exists
232
- try {
233
- await access(targetFile);
234
- // File exists - check if it's a PDS file by looking for our marker
235
- const existingContent = await readFile(targetFile, 'utf8');
236
- if (!existingContent.includes('Pure Design System (PDS)')) {
237
- // Not a PDS file, don't overwrite
238
- console.log('๐Ÿ“‹ Existing .github/copilot-instructions.md found (not PDS), skipping...');
239
- console.log(' ๐Ÿ’ก To use PDS instructions, run: npx pds-setup-copilot --force');
240
- return;
241
- }
242
- } catch {
243
- // File doesn't exist, we'll create it
244
- }
245
-
246
- await copyFile(sourceFile, targetFile);
247
- console.log('๐Ÿ“‹ Copied PDS Copilot instructions to .github/copilot-instructions.md');
248
-
249
- // Also copy .cursorrules for Cursor IDE users
250
- try {
251
- const cursorSource = path.join(repoRoot, '.cursorrules');
252
- const cursorTarget = path.join(consumerRoot, '.cursorrules');
253
-
254
- try {
255
- await access(cursorTarget);
256
- const existingCursor = await readFile(cursorTarget, 'utf8');
257
- if (!existingCursor.includes('Pure Design System (PDS)')) {
258
- console.log('๐Ÿ“‹ Existing .cursorrules found (not PDS), skipping...');
259
- return;
260
- }
261
- } catch {
262
- // File doesn't exist
263
- }
264
-
265
- await copyFile(cursorSource, cursorTarget);
266
- console.log('๐Ÿ“‹ Copied PDS instructions to .cursorrules (for Cursor IDE)');
267
- } catch (e) {
268
- // .cursorrules copy is optional
269
- }
270
- } catch (e) {
271
- console.warn('โš ๏ธ Could not copy Copilot instructions:', e.message);
272
- }
273
- }
274
-
275
- /**
276
- * Discover the web root directory using common patterns
277
- */
278
- async function discoverWebRoot(baseDir) {
279
- const cwd = baseDir || process.env.INIT_CWD || process.cwd();
280
-
281
- // Common web root patterns (in order of preference)
282
- const candidates = [
283
- 'public',
284
- 'static',
285
- 'dist',
286
- 'build',
287
- 'www',
288
- 'web',
289
- 'assets',
290
- 'src/assets',
291
- 'app/public',
292
- '.' // fallback to current directory
293
- ];
294
-
295
- console.log('๐Ÿ” Discovering web root directory...');
296
-
297
- for (const candidate of candidates) {
298
- const fullPath = path.resolve(cwd, candidate);
299
- try {
300
- await access(fullPath);
301
- const stats = await stat(fullPath);
302
- if (stats.isDirectory()) {
303
- console.log(` โœ… Found: ${candidate}/`);
304
- return { path: fullPath, relative: candidate };
305
- }
306
- } catch (e) {
307
- // Directory doesn't exist, continue
308
- }
309
- }
310
-
311
- // Check package.json for hints
312
- try {
313
- const packagePath = path.join(cwd, 'package.json');
314
- const pkg = JSON.parse(await readFile(packagePath, 'utf8'));
315
-
316
- // Look for common build/output directories in scripts
317
- const scripts = pkg.scripts || {};
318
- const scriptText = JSON.stringify(scripts);
319
-
320
- if (scriptText.includes('--outdir dist') || scriptText.includes('dist/')) {
321
- const distPath = path.resolve(cwd, 'dist');
322
- console.log(` ๐Ÿ’ก Found "dist" in scripts, using: dist/`);
323
- return { path: distPath, relative: 'dist' };
324
- }
325
-
326
- if (scriptText.includes('--outdir build') || scriptText.includes('build/')) {
327
- const buildPath = path.resolve(cwd, 'build');
328
- console.log(` ๐Ÿ’ก Found "build" in scripts, using: build/`);
329
- return { path: buildPath, relative: 'build' };
330
- }
331
-
332
- // Check for common framework configs
333
- if (pkg.dependencies?.['next'] || pkg.devDependencies?.['next']) {
334
- const publicPath = path.resolve(cwd, 'public');
335
- console.log(` ๐Ÿ”ง Next.js detected, using: public/`);
336
- return { path: publicPath, relative: 'public' };
337
- }
338
-
339
- if (pkg.dependencies?.['vite'] || pkg.devDependencies?.['vite']) {
340
- const publicPath = path.resolve(cwd, 'public');
341
- console.log(` โšก Vite detected, using: public/`);
342
- return { path: publicPath, relative: 'public' };
343
- }
344
-
345
- } catch (e) {
346
- // No package.json or parsing failed
347
- }
348
-
349
- // Ultimate fallback: create public directory
350
- const fallbackPath = path.resolve(cwd, 'public');
351
- console.log(` ๐Ÿ“ Creating fallback: public/`);
352
- await mkdir(fallbackPath, { recursive: true });
353
- return { path: fallbackPath, relative: 'public' };
354
- }
355
-
356
- /**
357
- * Copy PDS assets to the discovered web root
358
- */
359
- async function copyPdsAssets() {
360
- console.log('๐Ÿ“ฆ PDS postinstall running (no automatic component copy)โ€ฆ');
361
- try {
362
- const normalizedRepoRoot = normalizePath(repoRoot);
363
- const normalizedInitCwd = normalizePath(process.env.INIT_CWD || process.cwd());
364
-
365
- if (isLinkedPackagePath(normalizedRepoRoot)) {
366
- console.log('๐Ÿ›‘ Skipping PDS postinstall (detected symlinked package path).');
367
- return;
368
- }
369
-
370
- if (normalizedInitCwd === normalizedRepoRoot) {
371
- console.log('๐Ÿ›‘ Skipping PDS postinstall (working inside pure-ds repository root).');
372
- return;
373
- }
374
-
375
- if (isNpmLinkInvocation()) {
376
- console.log('๐Ÿ›‘ Skipping PDS postinstall (detected npm link invocation).');
377
- return;
378
- }
379
-
380
- if (isGlobalInstall()) {
381
- console.log('๐Ÿ›‘ Skipping PDS postinstall (global install detected).');
382
- return;
383
- }
384
-
385
- const consumerRoot = await findConsumerRoot();
386
- console.log('๐Ÿงช Consumer root:', consumerRoot);
387
-
388
- // Check if consumer package.json has "type": "module"
389
- try {
390
- const consumerPkgPath = path.join(consumerRoot, 'package.json');
391
- const consumerPkg = JSON.parse(await readFile(consumerPkgPath, 'utf8'));
392
-
393
- if (consumerPkg.type !== 'module') {
394
- console.error('\nโŒ ERROR: @pure-ds/core requires ES modules.\n');
395
- console.error('Add this to your package.json:\n');
396
- console.error(' "type": "module"\n');
397
- console.error('Then run: npm install @pure-ds/core\n');
398
- process.exit(1);
399
- }
400
- } catch (e) {
401
- console.error('โŒ Could not read consumer package.json:', e.message);
402
- process.exit(1);
403
- }
404
-
405
- // Allow opting out explicitly (useful for local dev / linking)
406
- if (
407
- process.env.PDS_SKIP_POSTINSTALL === '1' ||
408
- process.env.PDS_SKIP_POSTINSTALL === 'true' ||
409
- process.env.npm_config_pds_skip_postinstall === 'true'
410
- ) {
411
- console.log('โญ๏ธ Skipping PDS postinstall (PDS_SKIP_POSTINSTALL set).');
412
- return;
413
- }
414
-
415
- // If running inside the package repo itself (e.g., during `npm link`), skip
416
- const inRepo = normalizePath(consumerRoot) === normalizePath(repoRoot);
417
- const withinPureDs = isInstallingWithinPureDsRepo();
418
-
419
- if (inRepo || withinPureDs) {
420
- let reason = 'installing within pure-ds repository';
421
- if (inRepo) {
422
- reason = 'inside the package repo';
423
- } else if (withinPureDs) {
424
- reason = 'installing within pure-ds repository';
425
- }
426
- console.log(`๐Ÿ›‘ Skipping PDS postinstall (${reason}).`);
427
- return;
428
- }
429
-
430
- console.log('๐Ÿ“ฆ Proceeding with asset copying...');
431
-
432
- // Create default pds.config.js if it doesn't exist
433
- await ensurePdsConfig(consumerRoot);
434
-
435
- // Copy Copilot instructions to consumer project
436
- await copyCopilotInstructions(consumerRoot);
437
-
438
- // Copy getting started guide
439
- try {
440
- const sourceFile = path.join(repoRoot, 'getting-started.md');
441
- const targetFile = path.join(consumerRoot, 'getting-started.md');
442
- await copyFile(sourceFile, targetFile);
443
- console.log('๐Ÿ“– Copied getting-started.md to project root');
444
- } catch (e) {
445
- console.warn('โš ๏ธ Could not copy getting-started.md:', e.message);
446
- }
447
-
448
- // Proactively add export & build-icons scripts to consumer package.json (still helpful)
449
- await ensureExportScript(consumerRoot);
450
- try {
451
- const consumerPkgPath = path.join(consumerRoot, 'package.json');
452
- const pkgRaw = await readFile(consumerPkgPath, 'utf8');
453
- const pkgJson = JSON.parse(pkgRaw);
454
- pkgJson.scripts = pkgJson.scripts || {};
455
- const buildIconsName = 'pds:build-icons';
456
- const buildIconsCmd = 'pds-build-icons';
457
- if (!pkgJson.scripts[buildIconsName]) {
458
- pkgJson.scripts[buildIconsName] = buildIconsCmd;
459
- await writeFile(consumerPkgPath, JSON.stringify(pkgJson, null, 2) + '\n');
460
- console.log(`๐Ÿงฉ Added "${buildIconsName}" script to consumer package.json`);
461
- }
462
- } catch (e) {
463
- console.warn('โš ๏ธ Could not ensure pds:build-icons script in consumer package.json:', e?.message || e);
464
- }
465
-
466
- // NEW BEHAVIOR: We no longer copy web components automatically to /auto-define/.
467
- // Reason: static export (pds:export) is now the single source of truth for placing
468
- // components under [static.root]/components/ (see pds.config.js). This reduces
469
- // side-effects during npm install and avoids stale/legacy /auto-define/ layout.
470
- console.log('๐Ÿšซ Skipping legacy auto-copy of components to ./public/auto-define/.');
471
-
472
- // Auto-run pds:export by default (can be disabled with PDS_SKIP_EXPORT)
473
- if (
474
- process.env.PDS_SKIP_EXPORT === '1' ||
475
- process.env.PDS_SKIP_EXPORT === 'true' ||
476
- process.env.npm_config_pds_skip_export === 'true'
477
- ) {
478
- console.log('โญ๏ธ Skipping pds:export (PDS_SKIP_EXPORT set)');
479
- console.log('๐Ÿ“ฆ To generate static assets run: npm run pds:export');
480
- } else {
481
- console.log('๐Ÿš€ Running pds:export automatically...');
482
- const staticModuleUrl = pathToFileURL(path.join(__dirname, 'pds-static.mjs')).href;
483
- const previousEnv = {
484
- PDS_POSTINSTALL: process.env.PDS_POSTINSTALL,
485
- PDS_LOG_STREAM: process.env.PDS_LOG_STREAM,
486
- PDS_CONSUMER_ROOT: process.env.PDS_CONSUMER_ROOT,
487
- };
488
-
489
- try {
490
- process.env.PDS_POSTINSTALL = '1';
491
- process.env.PDS_LOG_STREAM = 'stderr';
492
- process.env.PDS_CONSUMER_ROOT = consumerRoot;
493
-
494
- const { runPdsStatic } = await import(staticModuleUrl);
495
- await runPdsStatic({ cwd: consumerRoot });
496
- } catch (e) {
497
- console.error('โŒ Auto-export failed:', e?.message || e);
498
- console.log('๐Ÿ’ก You can run it manually: npm run pds:export');
499
- } finally {
500
- if (previousEnv.PDS_POSTINSTALL === undefined) {
501
- delete process.env.PDS_POSTINSTALL;
502
- } else {
503
- process.env.PDS_POSTINSTALL = previousEnv.PDS_POSTINSTALL;
504
- }
505
-
506
- if (previousEnv.PDS_LOG_STREAM === undefined) {
507
- delete process.env.PDS_LOG_STREAM;
508
- } else {
509
- process.env.PDS_LOG_STREAM = previousEnv.PDS_LOG_STREAM;
510
- }
511
-
512
- if (previousEnv.PDS_CONSUMER_ROOT === undefined) {
513
- delete process.env.PDS_CONSUMER_ROOT;
514
- } else {
515
- process.env.PDS_CONSUMER_ROOT = previousEnv.PDS_CONSUMER_ROOT;
516
- }
517
- }
518
- }
519
-
520
- console.log('๐ŸŽจ (Optional) Build custom icons: npm run pds:build-icons');
521
- console.log('โ„น๏ธ If you previously relied on /auto-define/, update references to the new static output.');
522
-
523
- // Tracking file for diagnostics (minimal)
524
- try {
525
- const webRoot = await discoverWebRoot(consumerRoot);
526
- const trackingFile = path.join(webRoot.path, '.pds-install.json');
527
- const tracking = {
528
- version: '0.1.0',
529
- installDate: new Date().toISOString(),
530
- webRoot: webRoot.relative,
531
- componentsCopied: 0,
532
- mode: 'no-copy-postinstall',
533
- };
534
- await writeFile(trackingFile, JSON.stringify(tracking, null, 2));
535
- } catch (e) {
536
- console.warn('โš ๏ธ Could not write tracking file:', e?.message || e);
537
- }
538
-
539
- // Success summary (write to stderr so npm displays it)
540
- console.error('\nโœ… PDS installation complete!\n');
541
- try {
542
- const webRoot = await discoverWebRoot(consumerRoot);
543
- console.error(`๐Ÿ“ Assets installed to: ${webRoot.relative}/assets/pds/`);
544
- console.error('โš™๏ธ Configuration file: pds.config.js');
545
- console.error('๐Ÿ“‹ Copilot instructions: .github/copilot-instructions.md');
546
- console.error('โžค Cursor instructions: .cursorrules');
547
- console.error('๏ฟฝ Getting started guide: getting-started.md');
548
- console.error('๐Ÿ“š Get your own PDS Storybook via \'npm install @pure-ds/storybook\'\n');
549
- } catch {
550
- console.error('๐Ÿ“ฆ Run "npm run pds:export" to generate assets\n');
551
- }
552
- } catch (error) {
553
- console.error('โŒ PDS postinstall failed (non-fatal):', error.message);
554
- console.log('๐Ÿ’ก Static export still available via: npm run pds:export');
555
- process.exitCode = 1;
556
- }
557
- }
558
-
559
- // Only run when called directly (not when imported)
560
- if (process.argv[1] && (process.argv[1].endsWith('postinstall.mjs') || process.argv[1].endsWith('postinstall.js'))) {
561
- copyPdsAssets().catch(console.error);
562
- }
563
-
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * NPM postinstall script for @pure-ds/core
5
+ * Automatically copies PDS assets to the consuming app's web root
6
+ */
7
+
8
+ import { readFile, writeFile, mkdir, copyFile, readdir, stat, access, unlink } from 'fs/promises';
9
+ import { readFileSync } from 'fs';
10
+ import { createHash } from 'crypto';
11
+ import path from 'path';
12
+ import { fileURLToPath, pathToFileURL } from 'url';
13
+
14
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
15
+ const repoRoot = path.resolve(__dirname, '../../../');
16
+ const isWin = process.platform === 'win32';
17
+ const normalizePath = (p) => {
18
+ if (!p) return '';
19
+ const resolved = path.resolve(p).replace(/[\\/]+$/, '');
20
+ return isWin ? resolved.toLowerCase() : resolved;
21
+ };
22
+
23
+ /**
24
+ * Check if we're installing within the @pure-ds/core repo itself (not a consumer)
25
+ */
26
+ function isInstallingWithinPureDsRepo() {
27
+ try {
28
+ const cwd = process.cwd();
29
+ const initCwd = process.env.INIT_CWD || cwd;
30
+
31
+ // Check if the INIT_CWD has package.json with name "@pure-ds/core"
32
+ // This is more reliable than path comparison since repoRoot
33
+ // points to node_modules/@pure-ds/core when installed as a dependency
34
+ try {
35
+ const pkgPath = path.join(initCwd, 'package.json');
36
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
37
+ return pkg.name === '@pure-ds/core' || pkg.name === 'pure-ds';
38
+ } catch {
39
+ return false;
40
+ }
41
+ } catch (err) {
42
+ console.log('โš ๏ธ Error checking repo location:', err.message);
43
+ return false;
44
+ }
45
+ }
46
+
47
+ function isNpmLinkInvocation() {
48
+ const truthy = (value) => {
49
+ if (value === undefined || value === null) return false;
50
+ const normalized = String(value).toLowerCase();
51
+ return normalized === 'true' || normalized === '1';
52
+ };
53
+
54
+ if (truthy(process.env.npm_config_link)) return true;
55
+ if ((process.env.npm_command || '').toLowerCase() === 'link') return true;
56
+
57
+ try {
58
+ const argvRaw = process.env.npm_config_argv;
59
+ if (!argvRaw) return false;
60
+ const argv = JSON.parse(argvRaw);
61
+ const orig = argv && (argv.original || argv.cooked || []);
62
+ if (!Array.isArray(orig)) return false;
63
+ return orig.includes('link');
64
+ } catch {
65
+ return false;
66
+ }
67
+ }
68
+
69
+ function isLinkedPackagePath(p) {
70
+ return !/[\\/]+node_modules[\\/]+/i.test(p);
71
+ }
72
+
73
+ function isGlobalInstall() {
74
+ const value = process.env.npm_config_global;
75
+ if (!value) return false;
76
+ const normalized = String(value).toLowerCase();
77
+ return normalized === 'true' || normalized === '1';
78
+ }
79
+
80
+ /**
81
+ * Find the consumer app root (directory containing the consumer's package.json)
82
+ * Prefer INIT_CWD (npm sets this to the original cwd) and fallback by walking up from the package dir
83
+ */
84
+ async function findConsumerRoot() {
85
+ const tryPaths = [];
86
+ if (process.env.INIT_CWD) tryPaths.push(process.env.INIT_CWD);
87
+ // Walk up from the package dir until we exit node_modules
88
+ let dir = repoRoot;
89
+ while (dir && path.basename(dir) !== path.dirname(dir)) {
90
+ if (path.basename(dir) === 'node_modules') {
91
+ const candidate = path.dirname(dir);
92
+ tryPaths.push(candidate);
93
+ break;
94
+ }
95
+ dir = path.dirname(dir);
96
+ }
97
+
98
+ for (const p of tryPaths) {
99
+ try {
100
+ const pkgPath = path.join(p, 'package.json');
101
+ const pkg = JSON.parse(await readFile(pkgPath, 'utf8'));
102
+ if (pkg && pkg.name && pkg.name !== 'pure-ds') {
103
+ return p;
104
+ }
105
+ } catch {}
106
+ }
107
+
108
+ // Final fallback: INIT_CWD or current working dir
109
+ return process.env.INIT_CWD || process.cwd();
110
+ }
111
+
112
+ /**
113
+ * Ensure consumer package.json contains a handy export script
114
+ */
115
+ async function ensureExportScript(consumerRoot) {
116
+ try {
117
+ const consumerPkgPath = path.join(consumerRoot, 'package.json');
118
+ const consumerPkgRaw = await readFile(consumerPkgPath, 'utf8');
119
+ const consumerPkg = JSON.parse(consumerPkgRaw);
120
+
121
+ consumerPkg.scripts = consumerPkg.scripts || {};
122
+
123
+ const desiredScriptName = 'pds:export';
124
+ const desiredScriptCmd = 'pds-export';
125
+
126
+ if (!consumerPkg.scripts[desiredScriptName]) {
127
+ consumerPkg.scripts[desiredScriptName] = desiredScriptCmd;
128
+ await writeFile(consumerPkgPath, JSON.stringify(consumerPkg, null, 2) + '\n');
129
+ console.log(`๐Ÿงฉ Added "${desiredScriptName}" script to consumer package.json`);
130
+ } else {
131
+ console.log(`๐Ÿ”ง Script "${desiredScriptName}" already present in consumer package.json`);
132
+ }
133
+ } catch (e) {
134
+ console.warn('โš ๏ธ Could not ensure pds:export script in consumer package.json:', e.message);
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Create default pds.config.js if it doesn't exist
140
+ * @param {string} consumerRoot - The root directory to create the config in
141
+ * @param {boolean} force - If true, overwrite existing config
142
+ */
143
+ async function ensurePdsConfig(consumerRoot, force = false) {
144
+ try {
145
+ const configPath = path.join(consumerRoot, 'pds.config.js');
146
+
147
+ // Check if config already exists
148
+ try {
149
+ await access(configPath);
150
+ if (!force) {
151
+ console.log('๐Ÿ“ pds.config.js already exists, skipping...');
152
+ return;
153
+ }
154
+ console.log('๐Ÿ“ Overwriting existing pds.config.js...');
155
+ } catch {
156
+ // File doesn't exist, create it
157
+ }
158
+
159
+ const defaultConfig = `export const config = {
160
+ mode: "live",
161
+ preset: "default",
162
+
163
+ // Uncomment to override preset design tokens:
164
+ // design: {
165
+ // colors: {
166
+ // primary: '#007acc',
167
+ // secondary: '#5c2d91',
168
+ // accent: '#ec4899'
169
+ // },
170
+ // typography: {
171
+ // fontFamilyHeadings: 'Inter, sans-serif',
172
+ // fontFamilyBody: 'Inter, sans-serif',
173
+ // baseFontSize: 16,
174
+ // fontScale: 1.25
175
+ // },
176
+ // spatialRhythm: {
177
+ // baseUnit: 8,
178
+ // scaleRatio: 1.5
179
+ // }
180
+ // },
181
+
182
+ // Uncomment to add custom progressive enhancers:
183
+ // enhancers: [
184
+ // {
185
+ // selector: '[data-tooltip]',
186
+ // description: 'Adds tooltip on hover',
187
+ // run: (element) => {
188
+ // const text = element.dataset.tooltip;
189
+ // element.addEventListener('mouseenter', () => {
190
+ // // Show tooltip implementation
191
+ // });
192
+ // }
193
+ // }
194
+ // ],
195
+
196
+ // Uncomment to customize lazy-loaded web components:
197
+ // autoDefine: {
198
+ // baseURL: '/pds/components/',
199
+ // predefine: ['pds-icon', 'pds-drawer', 'pds-toaster'],
200
+ //
201
+ // // Custom component paths
202
+ // mapper: (tag) => {
203
+ // if (tag.startsWith('my-')) {
204
+ // return \`/components/\${tag}.js\`;
205
+ // }
206
+ // // Return nothing to use PDS default mapping
207
+ // }
208
+ // }
209
+ };
210
+ `;
211
+
212
+ await writeFile(configPath, defaultConfig, 'utf8');
213
+ console.log('๐Ÿ“ Created default pds.config.js');
214
+ } catch (e) {
215
+ console.warn('โš ๏ธ Could not create pds.config.js:', e.message);
216
+ }
217
+ }
218
+
219
+ /**
220
+ * Copy PDS Copilot instructions to consumer's .github folder
221
+ */
222
+ async function copyCopilotInstructions(consumerRoot) {
223
+ try {
224
+ const sourceFile = path.join(repoRoot, '.github', 'copilot-instructions.md');
225
+ const targetDir = path.join(consumerRoot, '.github');
226
+ const targetFile = path.join(targetDir, 'copilot-instructions.md');
227
+
228
+ // Create .github directory if it doesn't exist
229
+ await mkdir(targetDir, { recursive: true });
230
+
231
+ // Check if file already exists
232
+ try {
233
+ await access(targetFile);
234
+ // File exists - check if it's a PDS file by looking for our marker
235
+ const existingContent = await readFile(targetFile, 'utf8');
236
+ if (!existingContent.includes('Pure Design System (PDS)')) {
237
+ // Not a PDS file, don't overwrite
238
+ console.log('๐Ÿ“‹ Existing .github/copilot-instructions.md found (not PDS), skipping...');
239
+ console.log(' ๐Ÿ’ก To use PDS instructions, run: npx pds-setup-copilot --force');
240
+ return;
241
+ }
242
+ } catch {
243
+ // File doesn't exist, we'll create it
244
+ }
245
+
246
+ await copyFile(sourceFile, targetFile);
247
+ console.log('๐Ÿ“‹ Copied PDS Copilot instructions to .github/copilot-instructions.md');
248
+
249
+ // Also copy .cursorrules for Cursor IDE users
250
+ try {
251
+ const cursorSource = path.join(repoRoot, '.cursorrules');
252
+ const cursorTarget = path.join(consumerRoot, '.cursorrules');
253
+
254
+ try {
255
+ await access(cursorTarget);
256
+ const existingCursor = await readFile(cursorTarget, 'utf8');
257
+ if (!existingCursor.includes('Pure Design System (PDS)')) {
258
+ console.log('๐Ÿ“‹ Existing .cursorrules found (not PDS), skipping...');
259
+ return;
260
+ }
261
+ } catch {
262
+ // File doesn't exist
263
+ }
264
+
265
+ await copyFile(cursorSource, cursorTarget);
266
+ console.log('๐Ÿ“‹ Copied PDS instructions to .cursorrules (for Cursor IDE)');
267
+ } catch (e) {
268
+ // .cursorrules copy is optional
269
+ }
270
+ } catch (e) {
271
+ console.warn('โš ๏ธ Could not copy Copilot instructions:', e.message);
272
+ }
273
+ }
274
+
275
+ /**
276
+ * Discover the web root directory using common patterns
277
+ */
278
+ async function discoverWebRoot(baseDir) {
279
+ const cwd = baseDir || process.env.INIT_CWD || process.cwd();
280
+
281
+ // Common web root patterns (in order of preference)
282
+ const candidates = [
283
+ 'public',
284
+ 'static',
285
+ 'dist',
286
+ 'build',
287
+ 'www',
288
+ 'web',
289
+ 'assets',
290
+ 'src/assets',
291
+ 'app/public',
292
+ '.' // fallback to current directory
293
+ ];
294
+
295
+ console.log('๐Ÿ” Discovering web root directory...');
296
+
297
+ for (const candidate of candidates) {
298
+ const fullPath = path.resolve(cwd, candidate);
299
+ try {
300
+ await access(fullPath);
301
+ const stats = await stat(fullPath);
302
+ if (stats.isDirectory()) {
303
+ console.log(` โœ… Found: ${candidate}/`);
304
+ return { path: fullPath, relative: candidate };
305
+ }
306
+ } catch (e) {
307
+ // Directory doesn't exist, continue
308
+ }
309
+ }
310
+
311
+ // Check package.json for hints
312
+ try {
313
+ const packagePath = path.join(cwd, 'package.json');
314
+ const pkg = JSON.parse(await readFile(packagePath, 'utf8'));
315
+
316
+ // Look for common build/output directories in scripts
317
+ const scripts = pkg.scripts || {};
318
+ const scriptText = JSON.stringify(scripts);
319
+
320
+ if (scriptText.includes('--outdir dist') || scriptText.includes('dist/')) {
321
+ const distPath = path.resolve(cwd, 'dist');
322
+ console.log(` ๐Ÿ’ก Found "dist" in scripts, using: dist/`);
323
+ return { path: distPath, relative: 'dist' };
324
+ }
325
+
326
+ if (scriptText.includes('--outdir build') || scriptText.includes('build/')) {
327
+ const buildPath = path.resolve(cwd, 'build');
328
+ console.log(` ๐Ÿ’ก Found "build" in scripts, using: build/`);
329
+ return { path: buildPath, relative: 'build' };
330
+ }
331
+
332
+ // Check for common framework configs
333
+ if (pkg.dependencies?.['next'] || pkg.devDependencies?.['next']) {
334
+ const publicPath = path.resolve(cwd, 'public');
335
+ console.log(` ๐Ÿ”ง Next.js detected, using: public/`);
336
+ return { path: publicPath, relative: 'public' };
337
+ }
338
+
339
+ if (pkg.dependencies?.['vite'] || pkg.devDependencies?.['vite']) {
340
+ const publicPath = path.resolve(cwd, 'public');
341
+ console.log(` โšก Vite detected, using: public/`);
342
+ return { path: publicPath, relative: 'public' };
343
+ }
344
+
345
+ } catch (e) {
346
+ // No package.json or parsing failed
347
+ }
348
+
349
+ // Ultimate fallback: create public directory
350
+ const fallbackPath = path.resolve(cwd, 'public');
351
+ console.log(` ๐Ÿ“ Creating fallback: public/`);
352
+ await mkdir(fallbackPath, { recursive: true });
353
+ return { path: fallbackPath, relative: 'public' };
354
+ }
355
+
356
+ /**
357
+ * Copy PDS assets to the discovered web root
358
+ */
359
+ async function copyPdsAssets() {
360
+ console.log('๐Ÿ“ฆ PDS postinstall running (no automatic component copy)โ€ฆ');
361
+ try {
362
+ const normalizedRepoRoot = normalizePath(repoRoot);
363
+ const normalizedInitCwd = normalizePath(process.env.INIT_CWD || process.cwd());
364
+
365
+ if (isLinkedPackagePath(normalizedRepoRoot)) {
366
+ console.log('๐Ÿ›‘ Skipping PDS postinstall (detected symlinked package path).');
367
+ return;
368
+ }
369
+
370
+ if (normalizedInitCwd === normalizedRepoRoot) {
371
+ console.log('๐Ÿ›‘ Skipping PDS postinstall (working inside pure-ds repository root).');
372
+ return;
373
+ }
374
+
375
+ if (isNpmLinkInvocation()) {
376
+ console.log('๐Ÿ›‘ Skipping PDS postinstall (detected npm link invocation).');
377
+ return;
378
+ }
379
+
380
+ if (isGlobalInstall()) {
381
+ console.log('๐Ÿ›‘ Skipping PDS postinstall (global install detected).');
382
+ return;
383
+ }
384
+
385
+ const consumerRoot = await findConsumerRoot();
386
+ console.log('๐Ÿงช Consumer root:', consumerRoot);
387
+
388
+ // Allow opting out explicitly (useful for local dev / linking)
389
+ if (
390
+ process.env.PDS_SKIP_POSTINSTALL === '1' ||
391
+ process.env.PDS_SKIP_POSTINSTALL === 'true' ||
392
+ process.env.npm_config_pds_skip_postinstall === 'true'
393
+ ) {
394
+ console.log('โญ๏ธ Skipping PDS postinstall (PDS_SKIP_POSTINSTALL set).');
395
+ return;
396
+ }
397
+
398
+ // If running inside the package repo itself (e.g., during `npm link`), skip
399
+ const inRepo = normalizePath(consumerRoot) === normalizePath(repoRoot);
400
+ const withinPureDs = isInstallingWithinPureDsRepo();
401
+
402
+ if (inRepo || withinPureDs) {
403
+ let reason = 'installing within pure-ds repository';
404
+ if (inRepo) {
405
+ reason = 'inside the package repo';
406
+ } else if (withinPureDs) {
407
+ reason = 'installing within pure-ds repository';
408
+ }
409
+ console.log(`๐Ÿ›‘ Skipping PDS postinstall (${reason}).`);
410
+ return;
411
+ }
412
+
413
+ console.log('๐Ÿ“ฆ Proceeding with asset copying...');
414
+
415
+ // Create default pds.config.js if it doesn't exist
416
+ await ensurePdsConfig(consumerRoot);
417
+
418
+ // Copy Copilot instructions to consumer project
419
+ await copyCopilotInstructions(consumerRoot);
420
+
421
+ // Proactively add export & build-icons scripts to consumer package.json (still helpful)
422
+ await ensureExportScript(consumerRoot);
423
+ try {
424
+ const consumerPkgPath = path.join(consumerRoot, 'package.json');
425
+ const pkgRaw = await readFile(consumerPkgPath, 'utf8');
426
+ const pkgJson = JSON.parse(pkgRaw);
427
+ pkgJson.scripts = pkgJson.scripts || {};
428
+ const buildIconsName = 'pds:build-icons';
429
+ const buildIconsCmd = 'pds-build-icons';
430
+ if (!pkgJson.scripts[buildIconsName]) {
431
+ pkgJson.scripts[buildIconsName] = buildIconsCmd;
432
+ await writeFile(consumerPkgPath, JSON.stringify(pkgJson, null, 2) + '\n');
433
+ console.log(`๐Ÿงฉ Added "${buildIconsName}" script to consumer package.json`);
434
+ }
435
+ } catch (e) {
436
+ console.warn('โš ๏ธ Could not ensure pds:build-icons script in consumer package.json:', e?.message || e);
437
+ }
438
+
439
+ // NEW BEHAVIOR: We no longer copy web components automatically to /auto-define/.
440
+ // Reason: static export (pds:export) is now the single source of truth for placing
441
+ // components under [static.root]/components/ (see pds.config.js). This reduces
442
+ // side-effects during npm install and avoids stale/legacy /auto-define/ layout.
443
+ console.log('๐Ÿšซ Skipping legacy auto-copy of components to ./public/auto-define/.');
444
+
445
+ // Auto-run pds:export by default (can be disabled with PDS_SKIP_EXPORT)
446
+ if (
447
+ process.env.PDS_SKIP_EXPORT === '1' ||
448
+ process.env.PDS_SKIP_EXPORT === 'true' ||
449
+ process.env.npm_config_pds_skip_export === 'true'
450
+ ) {
451
+ console.log('โญ๏ธ Skipping pds:export (PDS_SKIP_EXPORT set)');
452
+ console.log('๐Ÿ“ฆ To generate static assets run: npm run pds:export');
453
+ } else {
454
+ console.log('๐Ÿš€ Running pds:export automatically...');
455
+ const staticModuleUrl = pathToFileURL(path.join(__dirname, 'pds-static.js')).href;
456
+ const previousEnv = {
457
+ PDS_POSTINSTALL: process.env.PDS_POSTINSTALL,
458
+ PDS_LOG_STREAM: process.env.PDS_LOG_STREAM,
459
+ PDS_CONSUMER_ROOT: process.env.PDS_CONSUMER_ROOT,
460
+ };
461
+
462
+ try {
463
+ process.env.PDS_POSTINSTALL = '1';
464
+ process.env.PDS_LOG_STREAM = 'stderr';
465
+ process.env.PDS_CONSUMER_ROOT = consumerRoot;
466
+
467
+ const { runPdsStatic } = await import(staticModuleUrl);
468
+ await runPdsStatic({ cwd: consumerRoot });
469
+ } catch (e) {
470
+ console.error('โŒ Auto-export failed:', e?.message || e);
471
+ console.log('๐Ÿ’ก You can run it manually: npm run pds:export');
472
+ } finally {
473
+ if (previousEnv.PDS_POSTINSTALL === undefined) {
474
+ delete process.env.PDS_POSTINSTALL;
475
+ } else {
476
+ process.env.PDS_POSTINSTALL = previousEnv.PDS_POSTINSTALL;
477
+ }
478
+
479
+ if (previousEnv.PDS_LOG_STREAM === undefined) {
480
+ delete process.env.PDS_LOG_STREAM;
481
+ } else {
482
+ process.env.PDS_LOG_STREAM = previousEnv.PDS_LOG_STREAM;
483
+ }
484
+
485
+ if (previousEnv.PDS_CONSUMER_ROOT === undefined) {
486
+ delete process.env.PDS_CONSUMER_ROOT;
487
+ } else {
488
+ process.env.PDS_CONSUMER_ROOT = previousEnv.PDS_CONSUMER_ROOT;
489
+ }
490
+ }
491
+ }
492
+
493
+ console.log('๐ŸŽจ (Optional) Build custom icons: npm run pds:build-icons');
494
+ console.log('โ„น๏ธ If you previously relied on /auto-define/, update references to the new static output.');
495
+
496
+ // Tracking file for diagnostics (minimal)
497
+ try {
498
+ const webRoot = await discoverWebRoot(consumerRoot);
499
+ const trackingFile = path.join(webRoot.path, '.pds-install.json');
500
+ const tracking = {
501
+ version: '0.1.0',
502
+ installDate: new Date().toISOString(),
503
+ webRoot: webRoot.relative,
504
+ componentsCopied: 0,
505
+ mode: 'no-copy-postinstall',
506
+ };
507
+ await writeFile(trackingFile, JSON.stringify(tracking, null, 2));
508
+ } catch (e) {
509
+ console.warn('โš ๏ธ Could not write tracking file:', e?.message || e);
510
+ }
511
+ } catch (error) {
512
+ console.error('โŒ PDS postinstall failed (non-fatal):', error.message);
513
+ console.log('๐Ÿ’ก Static export still available via: npm run pds:export');
514
+ process.exitCode = 1;
515
+ }
516
+ }
517
+
518
+ // Only run when called directly (not when imported)
519
+ if (process.argv[1] && (process.argv[1].endsWith('postinstall.mjs') || process.argv[1].endsWith('postinstall.js'))) {
520
+ copyPdsAssets().catch(console.error);
521
+ }
522
+
564
523
  export { copyPdsAssets, discoverWebRoot, ensurePdsConfig };