@strata-ds/core 2.1.17 → 2.1.19
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/README.md +48 -39
- package/dist/cli/postinstall.d.ts +1 -0
- package/dist/cli/postinstall.js +177 -0
- package/dist/cli/retrieve.d.ts +9 -0
- package/dist/cli/snapshot.js +181 -47
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -98,7 +98,7 @@ Your React Application
|
|
|
98
98
|
|
|
99
99
|
## Quick Start (< 5 Minutes)
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
Get your first component rendering in 4 steps.
|
|
102
102
|
|
|
103
103
|
### Step 1: Install
|
|
104
104
|
|
|
@@ -117,7 +117,7 @@ Go to [strata.charisol.io](https://strata.charisol.io) → **Your Project** →
|
|
|
117
117
|
|
|
118
118
|
### Step 3: Wrap Your App
|
|
119
119
|
|
|
120
|
-
|
|
120
|
+
**Recommended: CDN Snapshot Sync** (1 request per poll, edge-cached)
|
|
121
121
|
|
|
122
122
|
```tsx
|
|
123
123
|
"use client"; // Next.js App Router only
|
|
@@ -142,12 +142,12 @@ export default function RootLayout({
|
|
|
142
142
|
}
|
|
143
143
|
```
|
|
144
144
|
|
|
145
|
-
>
|
|
145
|
+
> Replace `YOUR_PROJECT_ID` and `pt_live_your_token_here` with values from **Step 2**.
|
|
146
146
|
|
|
147
147
|
---
|
|
148
148
|
|
|
149
149
|
<details>
|
|
150
|
-
<summary><strong
|
|
150
|
+
<summary><strong>Legacy Sync</strong> (3 requests per poll — for migration only)</summary>
|
|
151
151
|
|
|
152
152
|
```tsx
|
|
153
153
|
"use client";
|
|
@@ -173,9 +173,9 @@ export default function RootLayout({
|
|
|
173
173
|
|
|
174
174
|
**Why CDN is better:**
|
|
175
175
|
|
|
176
|
-
-
|
|
177
|
-
-
|
|
178
|
-
-
|
|
176
|
+
- 1 request instead of 3 (faster, cheaper)
|
|
177
|
+
- Edge-cached for global performance
|
|
178
|
+
- Atomic updates (no partial states)
|
|
179
179
|
|
|
180
180
|
</details>
|
|
181
181
|
|
|
@@ -224,10 +224,10 @@ Use this checklist to verify your setup after following [Quick Start](#quick-sta
|
|
|
224
224
|
|
|
225
225
|
**Verification:**
|
|
226
226
|
|
|
227
|
-
- [ ] Opened DevTools → Console and saw
|
|
228
|
-
- [ ] Console shows
|
|
227
|
+
- [ ] Opened DevTools → Console and saw `Starting design system sync...`
|
|
228
|
+
- [ ] Console shows `Components available: ...`
|
|
229
229
|
- [ ] Component renders on screen with correct styles
|
|
230
|
-
- [ ] Added `<StrataDebug />` and verified connection status is
|
|
230
|
+
- [ ] Added `<StrataDebug />` and verified connection status is **Connected**
|
|
231
231
|
|
|
232
232
|
**Stuck?** → Jump to [Debugging and Troubleshooting](#debugging-and-troubleshooting).
|
|
233
233
|
|
|
@@ -287,7 +287,7 @@ export default function RootLayout({
|
|
|
287
287
|
}
|
|
288
288
|
```
|
|
289
289
|
|
|
290
|
-
>
|
|
290
|
+
> Replace `YOUR_PROJECT_ID` with the ID from your Strata project dashboard. For private projects, add `syncToken="pt_live_your_token_here"` (get it from the **Publish & Sync** tab).
|
|
291
291
|
|
|
292
292
|
### Sync token authentication
|
|
293
293
|
|
|
@@ -359,10 +359,10 @@ function StatusBar() {
|
|
|
359
359
|
|
|
360
360
|
Add `<StrataDebug />` anywhere inside `<StrataProvider>` to inspect:
|
|
361
361
|
|
|
362
|
-
-
|
|
363
|
-
-
|
|
364
|
-
-
|
|
365
|
-
-
|
|
362
|
+
- Active sync mode (CDN vs Legacy)
|
|
363
|
+
- Connection status
|
|
364
|
+
- Loaded components
|
|
365
|
+
- Sync token presence (never shows the actual token)
|
|
366
366
|
|
|
367
367
|
```tsx
|
|
368
368
|
"use client";
|
|
@@ -380,11 +380,11 @@ function App() {
|
|
|
380
380
|
|
|
381
381
|
The panel automatically displays the relevant fields for the active sync mode:
|
|
382
382
|
|
|
383
|
-
- **CDN mode** (`snapshotCdnBase` + `projectId` set): shows
|
|
384
|
-
- **Legacy mode** (`syncUrl` set): shows
|
|
385
|
-
- **Disabled**: shows
|
|
383
|
+
- **CDN mode** (`snapshotCdnBase` + `projectId` set): shows `CDN Snapshot`, Project ID, resolved Snapshot URL, token presence, and sync interval.
|
|
384
|
+
- **Legacy mode** (`syncUrl` set): shows `Legacy (3 requests/poll)`, Sync URL, token presence, and sync interval.
|
|
385
|
+
- **Disabled**: shows `Disabled`.
|
|
386
386
|
|
|
387
|
-
>
|
|
387
|
+
> The `syncToken` value is **never** rendered — the panel only shows `Present` or `None`.
|
|
388
388
|
|
|
389
389
|
---
|
|
390
390
|
|
|
@@ -424,11 +424,11 @@ Open **DevTools → Network tab** and filter by:
|
|
|
424
424
|
|
|
425
425
|
Check for these messages:
|
|
426
426
|
|
|
427
|
-
-
|
|
428
|
-
-
|
|
429
|
-
-
|
|
430
|
-
-
|
|
431
|
-
-
|
|
427
|
+
- `Starting design system sync...` → Sync is working
|
|
428
|
+
- `Components available: Button, Navbar, Card` → Components loaded
|
|
429
|
+
- `Variables available: colors, spacing, typography` → Tokens loaded
|
|
430
|
+
- `Sync failed: 401` → Token issue (see table above)
|
|
431
|
+
- `Sync failed: 403` → CORS issue (see table above)
|
|
432
432
|
|
|
433
433
|
---
|
|
434
434
|
|
|
@@ -543,18 +543,27 @@ const MyComponent = StrataComponentFactory.createComponent(
|
|
|
543
543
|
|
|
544
544
|
Any project using the Strata Design System can enable full offline resilience in three quick steps:
|
|
545
545
|
|
|
546
|
-
#### Step 1:
|
|
547
|
-
Run the CLI
|
|
546
|
+
#### Step 1: Initialize Configuration with strata.json
|
|
547
|
+
Run the initialization CLI tool to prompt for configuration fields and generate a `strata.json` file in your application's root directory:
|
|
548
548
|
```bash
|
|
549
|
-
npx strata
|
|
550
|
-
--project-id "YOUR_PROJECT_ID" \
|
|
551
|
-
--cdn-base "https://your-cdn-base-url.cloudfront.net" \
|
|
552
|
-
--output "./src/data/strata-snapshot.json" \
|
|
553
|
-
--output-css "./src/styles/strata-fallbacks.css" \
|
|
554
|
-
--variables-only
|
|
549
|
+
npx strata init
|
|
555
550
|
```
|
|
551
|
+
This will create a `strata.json` file at your project's root:
|
|
552
|
+
```json
|
|
553
|
+
{
|
|
554
|
+
"projectId": "YOUR_PROJECT_ID",
|
|
555
|
+
"snapshotCdnBase": "https://your-cdn-base-url.cloudfront.net",
|
|
556
|
+
"output": "./src/data/strata-snapshot.json",
|
|
557
|
+
"outputCss": "./src/styles/strata-fallbacks.css",
|
|
558
|
+
"variablesOnly": true
|
|
559
|
+
}
|
|
560
|
+
```
|
|
561
|
+
|
|
556
562
|
*(Commit the generated JSON and CSS files to your Git repository as your baseline fallback).*
|
|
557
563
|
|
|
564
|
+
> **Manual Generation**: You can run the CLI snapshot tool manually if you need to fetch updates:
|
|
565
|
+
> `npx strata run`
|
|
566
|
+
|
|
558
567
|
#### Step 2: Import Fallback Styles
|
|
559
568
|
Reference the CSS file in your main style entry point (e.g., `src/index.css` or `src/App.css`):
|
|
560
569
|
```css
|
|
@@ -585,13 +594,13 @@ export default function App() {
|
|
|
585
594
|
|
|
586
595
|
## Key Features
|
|
587
596
|
|
|
588
|
-
-
|
|
589
|
-
-
|
|
590
|
-
-
|
|
591
|
-
-
|
|
592
|
-
-
|
|
593
|
-
-
|
|
594
|
-
-
|
|
597
|
+
- Live sync with Strata backend
|
|
598
|
+
- Token-driven styling
|
|
599
|
+
- Dynamic component registry
|
|
600
|
+
- Inline style overrides supported
|
|
601
|
+
- Installable via npm
|
|
602
|
+
- Offline-first fallback
|
|
603
|
+
- Debug tools included (`StrataDebug`)
|
|
595
604
|
|
|
596
605
|
## License
|
|
597
606
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
|
|
4
|
+
async function retrieveSnapshot(options) {
|
|
5
|
+
const { projectId, cdnBase, outputPath, outputCssPath, syncToken, variablesOnly } = options;
|
|
6
|
+
const base = cdnBase.replace(/\/+$/, '');
|
|
7
|
+
const snapshotUrl = base.endsWith('/snapshots')
|
|
8
|
+
? `${base}/${projectId}/strata.json`
|
|
9
|
+
: `${base}/snapshots/${projectId}/strata.json`;
|
|
10
|
+
console.log(`📡 Fetching snapshot from: ${snapshotUrl}`);
|
|
11
|
+
try {
|
|
12
|
+
const headers = {};
|
|
13
|
+
if (syncToken) {
|
|
14
|
+
headers['Authorization'] = `Bearer ${syncToken}`;
|
|
15
|
+
}
|
|
16
|
+
const res = await fetch(snapshotUrl, { headers });
|
|
17
|
+
if (!res.ok) {
|
|
18
|
+
throw new Error(`Server returned ${res.status} ${res.statusText}`);
|
|
19
|
+
}
|
|
20
|
+
const data = await res.json();
|
|
21
|
+
// Validate shape
|
|
22
|
+
if (!data || typeof data !== 'object' || typeof data.variables !== 'object') {
|
|
23
|
+
throw new Error('Invalid snapshot response shape: missing variables');
|
|
24
|
+
}
|
|
25
|
+
// Sanitize variables to prevent malformed values from breaking outputs
|
|
26
|
+
const variables = data.variables || {};
|
|
27
|
+
for (const [key, val] of Object.entries(variables)) {
|
|
28
|
+
if (val && typeof val === 'object') {
|
|
29
|
+
let value = val.value;
|
|
30
|
+
let resolvedValue = val.resolvedValue;
|
|
31
|
+
// Sanitize value
|
|
32
|
+
if (typeof value === 'string') {
|
|
33
|
+
if (value.endsWith('\\')) {
|
|
34
|
+
value += '\\';
|
|
35
|
+
}
|
|
36
|
+
if (value.startsWith('url(') && !value.endsWith(')')) {
|
|
37
|
+
if (value === 'url(\\' || value === 'url(\\\\' || value === 'url(\\;') {
|
|
38
|
+
value = 'none';
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
value += ')';
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
val.value = value;
|
|
45
|
+
}
|
|
46
|
+
// Sanitize resolvedValue
|
|
47
|
+
if (typeof resolvedValue === 'string') {
|
|
48
|
+
if (resolvedValue.endsWith('\\')) {
|
|
49
|
+
resolvedValue += '\\';
|
|
50
|
+
}
|
|
51
|
+
if (resolvedValue.startsWith('url(') && !resolvedValue.endsWith(')')) {
|
|
52
|
+
if (resolvedValue === 'url(\\' || resolvedValue === 'url(\\\\' || resolvedValue === 'url(\\;') {
|
|
53
|
+
resolvedValue = 'none';
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
resolvedValue += ')';
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
val.resolvedValue = resolvedValue;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
let snapshotJson = data;
|
|
64
|
+
if (variablesOnly) {
|
|
65
|
+
snapshotJson = {
|
|
66
|
+
variables: data.variables,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
// Write JSON output if requested
|
|
70
|
+
if (outputPath) {
|
|
71
|
+
const resolvedOutput = path.resolve(outputPath);
|
|
72
|
+
fs.mkdirSync(path.dirname(resolvedOutput), { recursive: true });
|
|
73
|
+
fs.writeFileSync(resolvedOutput, JSON.stringify(snapshotJson, null, 2), 'utf-8');
|
|
74
|
+
console.log(`✅ Snapshot JSON written to: ${resolvedOutput}`);
|
|
75
|
+
}
|
|
76
|
+
// Write CSS output if requested
|
|
77
|
+
if (outputCssPath) {
|
|
78
|
+
const resolvedCssOutput = path.resolve(outputCssPath);
|
|
79
|
+
fs.mkdirSync(path.dirname(resolvedCssOutput), { recursive: true });
|
|
80
|
+
let cssContent = `/* @strata-ds/core — Auto-generated CSS fallback variables\n`;
|
|
81
|
+
cssContent += ` * Project: ${projectId}\n`;
|
|
82
|
+
cssContent += ` * Generated: ${new Date().toISOString()}\n`;
|
|
83
|
+
cssContent += ` * DO NOT EDIT MANUALLY — regenerate with CLI snapshot tool\n`;
|
|
84
|
+
cssContent += ` */\n\n`;
|
|
85
|
+
cssContent += `:root {\n`;
|
|
86
|
+
const variables = data.variables || {};
|
|
87
|
+
for (const [key, val] of Object.entries(variables)) {
|
|
88
|
+
const resolvedVal = val.resolvedValue ?? val.value;
|
|
89
|
+
cssContent += ` ${key}: ${resolvedVal};\n`;
|
|
90
|
+
}
|
|
91
|
+
cssContent += `}\n`;
|
|
92
|
+
fs.writeFileSync(resolvedCssOutput, cssContent, 'utf-8');
|
|
93
|
+
console.log(`✅ CSS fallback written to: ${resolvedCssOutput}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
console.warn(`⚠️ Warning: Fetch failed: ${error.message || error}`);
|
|
98
|
+
// If fetch failed, check if output files already exist to degrade gracefully (exit 0)
|
|
99
|
+
let jsonExists = false;
|
|
100
|
+
let cssExists = false;
|
|
101
|
+
if (outputPath && fs.existsSync(path.resolve(outputPath))) {
|
|
102
|
+
jsonExists = true;
|
|
103
|
+
}
|
|
104
|
+
if (outputCssPath && fs.existsSync(path.resolve(outputCssPath))) {
|
|
105
|
+
cssExists = true;
|
|
106
|
+
}
|
|
107
|
+
const requestedOutputs = [];
|
|
108
|
+
if (outputPath)
|
|
109
|
+
requestedOutputs.push('JSON');
|
|
110
|
+
if (outputCssPath)
|
|
111
|
+
requestedOutputs.push('CSS');
|
|
112
|
+
const existingOutputs = [];
|
|
113
|
+
if (jsonExists)
|
|
114
|
+
existingOutputs.push('JSON');
|
|
115
|
+
if (cssExists)
|
|
116
|
+
existingOutputs.push('CSS');
|
|
117
|
+
if (requestedOutputs.length > 0 && requestedOutputs.length === existingOutputs.length) {
|
|
118
|
+
console.warn(`ℹ️ Existing output file(s) found. Graceful degradation: exiting 0.`);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
throw new Error('Fetch failed and no existing local outputs found to fall back on.');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function findHostStrataJson() {
|
|
128
|
+
let currentDir = process.cwd();
|
|
129
|
+
// Traverse up to find the host application's strata.json
|
|
130
|
+
while (true) {
|
|
131
|
+
const jsonPath = path.join(currentDir, 'strata.json');
|
|
132
|
+
if (fs.existsSync(jsonPath)) {
|
|
133
|
+
try {
|
|
134
|
+
const config = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
|
|
135
|
+
return { jsonPath, rootDir: currentDir, config };
|
|
136
|
+
}
|
|
137
|
+
catch (e) { }
|
|
138
|
+
}
|
|
139
|
+
const parentDir = path.dirname(currentDir);
|
|
140
|
+
if (parentDir === currentDir)
|
|
141
|
+
break;
|
|
142
|
+
currentDir = parentDir;
|
|
143
|
+
}
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
async function run() {
|
|
147
|
+
const hostInfo = findHostStrataJson();
|
|
148
|
+
if (!hostInfo) {
|
|
149
|
+
console.log('[Strata] No strata.json configuration file found. Run "npx strata init" to initialize design token fallback configuration.');
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const { rootDir, config } = hostInfo;
|
|
153
|
+
const { projectId, snapshotCdnBase, output, outputCss, syncToken, variablesOnly } = config;
|
|
154
|
+
if (!projectId || !snapshotCdnBase) {
|
|
155
|
+
console.warn('[Strata] Warning: "projectId" and "snapshotCdnBase" are required in strata.json config.');
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const outputPath = output ? path.resolve(rootDir, output) : undefined;
|
|
159
|
+
const outputCssPath = outputCss ? path.resolve(rootDir, outputCss) : undefined;
|
|
160
|
+
console.log(`[Strata] Postinstall: Fetching snapshot for project ${projectId}...`);
|
|
161
|
+
try {
|
|
162
|
+
await retrieveSnapshot({
|
|
163
|
+
projectId,
|
|
164
|
+
cdnBase: snapshotCdnBase,
|
|
165
|
+
outputPath,
|
|
166
|
+
outputCssPath,
|
|
167
|
+
syncToken,
|
|
168
|
+
variablesOnly: variablesOnly !== false,
|
|
169
|
+
});
|
|
170
|
+
console.log('[Strata] Postinstall snapshot retrieval complete.');
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
// Graceful degradation: log warning but do not throw error so install succeeds
|
|
174
|
+
console.warn(`[Strata] Postinstall snapshot failed: ${error.message || error}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
run();
|
package/dist/cli/snapshot.js
CHANGED
|
@@ -2,51 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import * as fs from 'fs';
|
|
4
4
|
import * as path from 'path';
|
|
5
|
+
import * as readline from 'readline';
|
|
5
6
|
|
|
6
|
-
function
|
|
7
|
-
|
|
8
|
-
Strata Design System Snapshot CLI
|
|
9
|
-
|
|
10
|
-
Usage:
|
|
11
|
-
npx strata-ds [options]
|
|
12
|
-
|
|
13
|
-
Options:
|
|
14
|
-
--project-id Strata Project ID (required)
|
|
15
|
-
--cdn-base CDN base URL (e.g. https://dx2nhw7wqn4nn.cloudfront.net) (required)
|
|
16
|
-
--output Path to write the snapshot JSON file (optional)
|
|
17
|
-
--output-css Path to write the CSS fallback file (optional)
|
|
18
|
-
--sync-token Authorization Sync Token (optional)
|
|
19
|
-
--variables-only Only output variables in the snapshot JSON (optional)
|
|
20
|
-
--help, -h Show help
|
|
21
|
-
`);
|
|
22
|
-
}
|
|
23
|
-
async function run() {
|
|
24
|
-
const args = process.argv.slice(2);
|
|
25
|
-
if (args.includes('--help') || args.includes('-h') || args.length === 0) {
|
|
26
|
-
printHelp();
|
|
27
|
-
process.exit(0);
|
|
28
|
-
}
|
|
29
|
-
const getArgValue = (flag) => {
|
|
30
|
-
const idx = args.indexOf(flag);
|
|
31
|
-
if (idx !== -1 && idx + 1 < args.length) {
|
|
32
|
-
return args[idx + 1];
|
|
33
|
-
}
|
|
34
|
-
return undefined;
|
|
35
|
-
};
|
|
36
|
-
const hasFlag = (flag) => {
|
|
37
|
-
return args.includes(flag);
|
|
38
|
-
};
|
|
39
|
-
const projectId = getArgValue('--project-id');
|
|
40
|
-
const cdnBase = getArgValue('--cdn-base');
|
|
41
|
-
const outputPath = getArgValue('--output');
|
|
42
|
-
const outputCssPath = getArgValue('--output-css');
|
|
43
|
-
const syncToken = getArgValue('--sync-token');
|
|
44
|
-
const variablesOnly = hasFlag('--variables-only');
|
|
45
|
-
if (!projectId || !cdnBase) {
|
|
46
|
-
console.error('❌ Error: --project-id and --cdn-base are required.');
|
|
47
|
-
printHelp();
|
|
48
|
-
process.exit(1);
|
|
49
|
-
}
|
|
7
|
+
async function retrieveSnapshot(options) {
|
|
8
|
+
const { projectId, cdnBase, outputPath, outputCssPath, syncToken, variablesOnly } = options;
|
|
50
9
|
const base = cdnBase.replace(/\/+$/, '');
|
|
51
10
|
const snapshotUrl = base.endsWith('/snapshots')
|
|
52
11
|
? `${base}/${projectId}/strata.json`
|
|
@@ -66,6 +25,44 @@ async function run() {
|
|
|
66
25
|
if (!data || typeof data !== 'object' || typeof data.variables !== 'object') {
|
|
67
26
|
throw new Error('Invalid snapshot response shape: missing variables');
|
|
68
27
|
}
|
|
28
|
+
// Sanitize variables to prevent malformed values from breaking outputs
|
|
29
|
+
const variables = data.variables || {};
|
|
30
|
+
for (const [key, val] of Object.entries(variables)) {
|
|
31
|
+
if (val && typeof val === 'object') {
|
|
32
|
+
let value = val.value;
|
|
33
|
+
let resolvedValue = val.resolvedValue;
|
|
34
|
+
// Sanitize value
|
|
35
|
+
if (typeof value === 'string') {
|
|
36
|
+
if (value.endsWith('\\')) {
|
|
37
|
+
value += '\\';
|
|
38
|
+
}
|
|
39
|
+
if (value.startsWith('url(') && !value.endsWith(')')) {
|
|
40
|
+
if (value === 'url(\\' || value === 'url(\\\\' || value === 'url(\\;') {
|
|
41
|
+
value = 'none';
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
value += ')';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
val.value = value;
|
|
48
|
+
}
|
|
49
|
+
// Sanitize resolvedValue
|
|
50
|
+
if (typeof resolvedValue === 'string') {
|
|
51
|
+
if (resolvedValue.endsWith('\\')) {
|
|
52
|
+
resolvedValue += '\\';
|
|
53
|
+
}
|
|
54
|
+
if (resolvedValue.startsWith('url(') && !resolvedValue.endsWith(')')) {
|
|
55
|
+
if (resolvedValue === 'url(\\' || resolvedValue === 'url(\\\\' || resolvedValue === 'url(\\;') {
|
|
56
|
+
resolvedValue = 'none';
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
resolvedValue += ')';
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
val.resolvedValue = resolvedValue;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
69
66
|
let snapshotJson = data;
|
|
70
67
|
if (variablesOnly) {
|
|
71
68
|
snapshotJson = {
|
|
@@ -122,12 +119,149 @@ async function run() {
|
|
|
122
119
|
existingOutputs.push('CSS');
|
|
123
120
|
if (requestedOutputs.length > 0 && requestedOutputs.length === existingOutputs.length) {
|
|
124
121
|
console.warn(`ℹ️ Existing output file(s) found. Graceful degradation: exiting 0.`);
|
|
125
|
-
|
|
122
|
+
return;
|
|
126
123
|
}
|
|
127
124
|
else {
|
|
128
|
-
|
|
125
|
+
throw new Error('Fetch failed and no existing local outputs found to fall back on.');
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function printHelp() {
|
|
131
|
+
console.log(`
|
|
132
|
+
Strata Design System Snapshot CLI
|
|
133
|
+
|
|
134
|
+
Usage:
|
|
135
|
+
npx strata [command] [options]
|
|
136
|
+
|
|
137
|
+
Commands:
|
|
138
|
+
init Interactively initialize strata.json configuration file
|
|
139
|
+
run Fetch snapshot and generate fallbacks using strata.json
|
|
140
|
+
snapshot Legacy command to fetch snapshot using options
|
|
141
|
+
|
|
142
|
+
Options:
|
|
143
|
+
--project-id Strata Project ID (overrides strata.json)
|
|
144
|
+
--cdn-base CDN base URL (overrides strata.json)
|
|
145
|
+
--output Path to write the snapshot JSON file (overrides strata.json)
|
|
146
|
+
--output-css Path to write the CSS fallback file (overrides strata.json)
|
|
147
|
+
--sync-token Authorization Sync Token (overrides strata.json)
|
|
148
|
+
--variables-only Only output variables in the snapshot JSON (overrides strata.json)
|
|
149
|
+
--help, -h Show help
|
|
150
|
+
`);
|
|
151
|
+
}
|
|
152
|
+
function askQuestion(query) {
|
|
153
|
+
const rl = readline.createInterface({
|
|
154
|
+
input: process.stdin,
|
|
155
|
+
output: process.stdout,
|
|
156
|
+
});
|
|
157
|
+
return new Promise((resolve) => rl.question(query, (ans) => {
|
|
158
|
+
rl.close();
|
|
159
|
+
resolve(ans.trim());
|
|
160
|
+
}));
|
|
161
|
+
}
|
|
162
|
+
async function runInit() {
|
|
163
|
+
console.log('Strata Design System Initialization\n');
|
|
164
|
+
let projectId = '';
|
|
165
|
+
while (!projectId) {
|
|
166
|
+
projectId = await askQuestion('Enter your Strata Project ID (required): ');
|
|
167
|
+
if (!projectId) {
|
|
168
|
+
console.log('Error: Project ID is required.');
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const cdnBase = (await askQuestion('Enter CDN Base URL (default: https://dx2nhw7wqn4nn.cloudfront.net): ')) || 'https://dx2nhw7wqn4nn.cloudfront.net';
|
|
172
|
+
const output = (await askQuestion('Enter path to write snapshot JSON file (default: ./src/data/strata-snapshot.json): ')) || './src/data/strata-snapshot.json';
|
|
173
|
+
const outputCss = (await askQuestion('Enter path to write CSS fallback file (default: ./src/styles/strata-fallbacks.css): ')) || './src/styles/strata-fallbacks.css';
|
|
174
|
+
const varsOnlyInput = await askQuestion('Only output variables in snapshot JSON? (Y/n): ');
|
|
175
|
+
const variablesOnly = varsOnlyInput.toLowerCase() !== 'n';
|
|
176
|
+
const config = {
|
|
177
|
+
projectId,
|
|
178
|
+
snapshotCdnBase: cdnBase,
|
|
179
|
+
output,
|
|
180
|
+
outputCss,
|
|
181
|
+
variablesOnly,
|
|
182
|
+
};
|
|
183
|
+
const strataJsonPath = path.join(process.cwd(), 'strata.json');
|
|
184
|
+
fs.writeFileSync(strataJsonPath, JSON.stringify(config, null, 2), 'utf8');
|
|
185
|
+
console.log(`\nConfig file written successfully to: ${strataJsonPath}`);
|
|
186
|
+
console.log('To fetch your design tokens, run: npx strata run');
|
|
187
|
+
}
|
|
188
|
+
async function runRetrieve(command) {
|
|
189
|
+
const args = process.argv.slice(2);
|
|
190
|
+
const getArgValue = (flag) => {
|
|
191
|
+
const idx = args.indexOf(flag);
|
|
192
|
+
if (idx !== -1 && idx + 1 < args.length) {
|
|
193
|
+
return args[idx + 1];
|
|
194
|
+
}
|
|
195
|
+
return undefined;
|
|
196
|
+
};
|
|
197
|
+
const hasFlag = (flag) => {
|
|
198
|
+
return args.includes(flag);
|
|
199
|
+
};
|
|
200
|
+
// Load config from strata.json if it exists
|
|
201
|
+
const strataJsonPath = path.join(process.cwd(), 'strata.json');
|
|
202
|
+
let config = {};
|
|
203
|
+
if (fs.existsSync(strataJsonPath)) {
|
|
204
|
+
try {
|
|
205
|
+
config = JSON.parse(fs.readFileSync(strataJsonPath, 'utf8'));
|
|
206
|
+
}
|
|
207
|
+
catch (e) {
|
|
208
|
+
console.error(`Error reading strata.json: ${e.message}`);
|
|
129
209
|
process.exit(1);
|
|
130
210
|
}
|
|
131
211
|
}
|
|
212
|
+
else if (command === 'run') {
|
|
213
|
+
console.error('Error: strata.json not found. Run "npx strata init" to initialize configuration.');
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
const projectId = getArgValue('--project-id') || config.projectId;
|
|
217
|
+
const cdnBase = getArgValue('--cdn-base') || config.snapshotCdnBase;
|
|
218
|
+
const outputPath = getArgValue('--output') || config.output;
|
|
219
|
+
const outputCssPath = getArgValue('--output-css') || config.outputCss;
|
|
220
|
+
const syncToken = getArgValue('--sync-token') || config.syncToken;
|
|
221
|
+
// variables-only is true by default if not set to false
|
|
222
|
+
let variablesOnly = true;
|
|
223
|
+
if (hasFlag('--variables-only')) {
|
|
224
|
+
variablesOnly = true;
|
|
225
|
+
}
|
|
226
|
+
else if (config.variablesOnly !== undefined) {
|
|
227
|
+
variablesOnly = config.variablesOnly;
|
|
228
|
+
}
|
|
229
|
+
if (!projectId || !cdnBase) {
|
|
230
|
+
console.error('Error: --project-id and --cdn-base are required (or must be configured in strata.json).');
|
|
231
|
+
printHelp();
|
|
232
|
+
process.exit(1);
|
|
233
|
+
}
|
|
234
|
+
try {
|
|
235
|
+
await retrieveSnapshot({
|
|
236
|
+
projectId,
|
|
237
|
+
cdnBase,
|
|
238
|
+
outputPath: outputPath ? path.resolve(outputPath) : undefined,
|
|
239
|
+
outputCssPath: outputCssPath ? path.resolve(outputCssPath) : undefined,
|
|
240
|
+
syncToken,
|
|
241
|
+
variablesOnly,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
console.error(`Error: ${error.message || error}`);
|
|
246
|
+
process.exit(1);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
async function main() {
|
|
250
|
+
const args = process.argv.slice(2);
|
|
251
|
+
const command = args[0];
|
|
252
|
+
if (args.includes('--help') || args.includes('-h') || !command) {
|
|
253
|
+
printHelp();
|
|
254
|
+
process.exit(0);
|
|
255
|
+
}
|
|
256
|
+
if (command === 'init') {
|
|
257
|
+
await runInit();
|
|
258
|
+
}
|
|
259
|
+
else if (command === 'run' || command === 'snapshot') {
|
|
260
|
+
await runRetrieve(command);
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
// If it's not a recognized command, default to legacy options-based fetch
|
|
264
|
+
await runRetrieve('legacy');
|
|
265
|
+
}
|
|
132
266
|
}
|
|
133
|
-
|
|
267
|
+
main();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strata-ds/core",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.19",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The runtime component library for Strata — design once, sync everywhere.",
|
|
6
6
|
"homepage": "https://strata.charisol.io",
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
"module": "dist/index.esm.js",
|
|
9
9
|
"types": "dist/index.d.ts",
|
|
10
10
|
"bin": {
|
|
11
|
-
"strata-ds": "./dist/cli/snapshot.js"
|
|
11
|
+
"strata-ds": "./dist/cli/snapshot.js",
|
|
12
|
+
"strata": "./dist/cli/snapshot.js"
|
|
12
13
|
},
|
|
13
14
|
"exports": {
|
|
14
15
|
".": {
|
|
@@ -25,7 +26,8 @@
|
|
|
25
26
|
"build": "rollup -c",
|
|
26
27
|
"dev": "rollup -c -w",
|
|
27
28
|
"build:css": "tailwindcss -i ./src/styles.css -o ./dist/styles.css --minify",
|
|
28
|
-
"prepublishOnly": "npm run build"
|
|
29
|
+
"prepublishOnly": "npm run build",
|
|
30
|
+
"postinstall": "node -e \"if (require('fs').existsSync('./dist/cli/postinstall.js')) import('./dist/cli/postinstall.js')\""
|
|
29
31
|
},
|
|
30
32
|
"keywords": [
|
|
31
33
|
"strata",
|