@strata-ds/core 2.1.16 → 2.1.18

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 CHANGED
@@ -524,6 +524,8 @@ const MyComponent = StrataComponentFactory.createComponent(
524
524
  componentData,
525
525
  designSystem,
526
526
  );
527
+ ```
528
+
527
529
  ## Offline Resilience & Build-Time Fallbacks
528
530
 
529
531
  `@strata-ds/core` is built to be completely resilient to network outages, CDN downtime, or slow connections using a multi-layered fallback strategy.
@@ -541,18 +543,27 @@ const MyComponent = StrataComponentFactory.createComponent(
541
543
 
542
544
  Any project using the Strata Design System can enable full offline resilience in three quick steps:
543
545
 
544
- #### Step 1: Generate the Local Snapshot and Fallback CSS
545
- Run the CLI snapshot tool locally or add it to your project's build process:
546
- ```bash
547
- npx strata-ds snapshot \
548
- --project-id "YOUR_PROJECT_ID" \
549
- --cdn-base "https://your-cdn-base-url.cloudfront.net" \
550
- --output "./src/data/strata-snapshot.json" \
551
- --output-css "./src/styles/strata-fallbacks.css" \
552
- --variables-only
546
+ #### Step 1: Configure Auto-Generation in `package.json`
547
+ Simply add a `"strata"` configuration block to your application's `package.json`. The SDK's built-in postinstall hook will automatically fetch the latest snapshot and generate the fallback assets every time you run `npm install`:
548
+
549
+ ```json
550
+ {
551
+ "name": "your-app",
552
+ "strata": {
553
+ "projectId": "YOUR_PROJECT_ID",
554
+ "snapshotCdnBase": "https://your-cdn-base-url.cloudfront.net",
555
+ "output": "./src/data/strata-snapshot.json",
556
+ "outputCss": "./src/styles/strata-fallbacks.css",
557
+ "variablesOnly": true
558
+ }
559
+ }
553
560
  ```
561
+
554
562
  *(Commit the generated JSON and CSS files to your Git repository as your baseline fallback).*
555
563
 
564
+ > 💡 **Manual Generation**: You can also run the CLI snapshot tool manually if needed:
565
+ > `npx strata-ds snapshot --project-id "YOUR_PROJECT_ID" --cdn-base "https://your-cdn-base-url.cloudfront.net" --output "./src/data/strata-snapshot.json" --output-css "./src/styles/strata-fallbacks.css" --variables-only`
566
+
556
567
  #### Step 2: Import Fallback Styles
557
568
  Reference the CSS file in your main style entry point (e.g., `src/index.css` or `src/App.css`):
558
569
  ```css
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,141 @@
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
+ let snapshotJson = data;
26
+ if (variablesOnly) {
27
+ snapshotJson = {
28
+ variables: data.variables,
29
+ };
30
+ }
31
+ // Write JSON output if requested
32
+ if (outputPath) {
33
+ const resolvedOutput = path.resolve(outputPath);
34
+ fs.mkdirSync(path.dirname(resolvedOutput), { recursive: true });
35
+ fs.writeFileSync(resolvedOutput, JSON.stringify(snapshotJson, null, 2), 'utf-8');
36
+ console.log(`✅ Snapshot JSON written to: ${resolvedOutput}`);
37
+ }
38
+ // Write CSS output if requested
39
+ if (outputCssPath) {
40
+ const resolvedCssOutput = path.resolve(outputCssPath);
41
+ fs.mkdirSync(path.dirname(resolvedCssOutput), { recursive: true });
42
+ let cssContent = `/* @strata-ds/core — Auto-generated CSS fallback variables\n`;
43
+ cssContent += ` * Project: ${projectId}\n`;
44
+ cssContent += ` * Generated: ${new Date().toISOString()}\n`;
45
+ cssContent += ` * DO NOT EDIT MANUALLY — regenerate with CLI snapshot tool\n`;
46
+ cssContent += ` */\n\n`;
47
+ cssContent += `:root {\n`;
48
+ const variables = data.variables || {};
49
+ for (const [key, val] of Object.entries(variables)) {
50
+ const resolvedVal = val.resolvedValue ?? val.value;
51
+ cssContent += ` ${key}: ${resolvedVal};\n`;
52
+ }
53
+ cssContent += `}\n`;
54
+ fs.writeFileSync(resolvedCssOutput, cssContent, 'utf-8');
55
+ console.log(`✅ CSS fallback written to: ${resolvedCssOutput}`);
56
+ }
57
+ }
58
+ catch (error) {
59
+ console.warn(`âš ī¸ Warning: Fetch failed: ${error.message || error}`);
60
+ // If fetch failed, check if output files already exist to degrade gracefully (exit 0)
61
+ let jsonExists = false;
62
+ let cssExists = false;
63
+ if (outputPath && fs.existsSync(path.resolve(outputPath))) {
64
+ jsonExists = true;
65
+ }
66
+ if (outputCssPath && fs.existsSync(path.resolve(outputCssPath))) {
67
+ cssExists = true;
68
+ }
69
+ const requestedOutputs = [];
70
+ if (outputPath)
71
+ requestedOutputs.push('JSON');
72
+ if (outputCssPath)
73
+ requestedOutputs.push('CSS');
74
+ const existingOutputs = [];
75
+ if (jsonExists)
76
+ existingOutputs.push('JSON');
77
+ if (cssExists)
78
+ existingOutputs.push('CSS');
79
+ if (requestedOutputs.length > 0 && requestedOutputs.length === existingOutputs.length) {
80
+ console.warn(`â„šī¸ Existing output file(s) found. Graceful degradation: exiting 0.`);
81
+ return;
82
+ }
83
+ else {
84
+ throw new Error('Fetch failed and no existing local outputs found to fall back on.');
85
+ }
86
+ }
87
+ }
88
+
89
+ function findHostPackage() {
90
+ let currentDir = process.cwd();
91
+ // Traverse up to find the host application's package.json
92
+ while (true) {
93
+ const packagePath = path.join(currentDir, 'package.json');
94
+ if (fs.existsSync(packagePath)) {
95
+ try {
96
+ const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
97
+ if (pkg.name !== '@strata-ds/core' && pkg.strata) {
98
+ return { packagePath, rootDir: currentDir, config: pkg.strata };
99
+ }
100
+ }
101
+ catch (e) { }
102
+ }
103
+ const parentDir = path.dirname(currentDir);
104
+ if (parentDir === currentDir)
105
+ break;
106
+ currentDir = parentDir;
107
+ }
108
+ return null;
109
+ }
110
+ async function run() {
111
+ const hostInfo = findHostPackage();
112
+ if (!hostInfo) {
113
+ console.log('[Strata] No "strata" configuration block found in host package.json. Skipping auto-snapshot retrieval.');
114
+ return;
115
+ }
116
+ const { rootDir, config } = hostInfo;
117
+ const { projectId, snapshotCdnBase, output, outputCss, syncToken, variablesOnly } = config;
118
+ if (!projectId || !snapshotCdnBase) {
119
+ console.warn('[Strata] Warning: "projectId" and "snapshotCdnBase" are required in package.json "strata" config.');
120
+ return;
121
+ }
122
+ const outputPath = output ? path.resolve(rootDir, output) : undefined;
123
+ const outputCssPath = outputCss ? path.resolve(rootDir, outputCss) : undefined;
124
+ console.log(`[Strata] Postinstall: Fetching snapshot for project ${projectId}...`);
125
+ try {
126
+ await retrieveSnapshot({
127
+ projectId,
128
+ cdnBase: snapshotCdnBase,
129
+ outputPath,
130
+ outputCssPath,
131
+ syncToken,
132
+ variablesOnly: variablesOnly !== false, // default to true for post-install variable trimming
133
+ });
134
+ console.log('✅ [Strata] Postinstall snapshot retrieval complete.');
135
+ }
136
+ catch (error) {
137
+ // Graceful degradation: log warning but do not throw error so install succeeds
138
+ console.warn(`âš ī¸ [Strata] Postinstall snapshot failed: ${error.message || error}`);
139
+ }
140
+ }
141
+ run();
@@ -0,0 +1,9 @@
1
+ export interface RetrieveOptions {
2
+ projectId: string;
3
+ cdnBase: string;
4
+ outputPath?: string;
5
+ outputCssPath?: string;
6
+ syncToken?: string;
7
+ variablesOnly?: boolean;
8
+ }
9
+ export declare function retrieveSnapshot(options: RetrieveOptions): Promise<void>;
@@ -3,50 +3,8 @@
3
3
  import * as fs from 'fs';
4
4
  import * as path from 'path';
5
5
 
6
- function printHelp() {
7
- console.log(`
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
- }
6
+ async function retrieveSnapshot(options) {
7
+ const { projectId, cdnBase, outputPath, outputCssPath, syncToken, variablesOnly } = options;
50
8
  const base = cdnBase.replace(/\/+$/, '');
51
9
  const snapshotUrl = base.endsWith('/snapshots')
52
10
  ? `${base}/${projectId}/strata.json`
@@ -122,12 +80,71 @@ async function run() {
122
80
  existingOutputs.push('CSS');
123
81
  if (requestedOutputs.length > 0 && requestedOutputs.length === existingOutputs.length) {
124
82
  console.warn(`â„šī¸ Existing output file(s) found. Graceful degradation: exiting 0.`);
125
- process.exit(0);
83
+ return;
126
84
  }
127
85
  else {
128
- console.error('❌ Error: Fetch failed and no existing local outputs found to fall back on.');
129
- process.exit(1);
86
+ throw new Error('Fetch failed and no existing local outputs found to fall back on.');
130
87
  }
131
88
  }
132
89
  }
90
+
91
+ function printHelp() {
92
+ console.log(`
93
+ Strata Design System Snapshot CLI
94
+
95
+ Usage:
96
+ npx strata-ds snapshot [options]
97
+
98
+ Options:
99
+ --project-id Strata Project ID (required)
100
+ --cdn-base CDN base URL (e.g. https://dx2nhw7wqn4nn.cloudfront.net) (required)
101
+ --output Path to write the snapshot JSON file (optional)
102
+ --output-css Path to write the CSS fallback file (optional)
103
+ --sync-token Authorization Sync Token (optional)
104
+ --variables-only Only output variables in the snapshot JSON (optional)
105
+ --help, -h Show help
106
+ `);
107
+ }
108
+ async function run() {
109
+ const args = process.argv.slice(2);
110
+ if (args.includes('--help') || args.includes('-h') || args.length === 0) {
111
+ printHelp();
112
+ process.exit(0);
113
+ }
114
+ const getArgValue = (flag) => {
115
+ const idx = args.indexOf(flag);
116
+ if (idx !== -1 && idx + 1 < args.length) {
117
+ return args[idx + 1];
118
+ }
119
+ return undefined;
120
+ };
121
+ const hasFlag = (flag) => {
122
+ return args.includes(flag);
123
+ };
124
+ const projectId = getArgValue('--project-id');
125
+ const cdnBase = getArgValue('--cdn-base');
126
+ const outputPath = getArgValue('--output');
127
+ const outputCssPath = getArgValue('--output-css');
128
+ const syncToken = getArgValue('--sync-token');
129
+ const variablesOnly = hasFlag('--variables-only');
130
+ if (!projectId || !cdnBase) {
131
+ console.error('❌ Error: --project-id and --cdn-base are required.');
132
+ printHelp();
133
+ process.exit(1);
134
+ }
135
+ try {
136
+ await retrieveSnapshot({
137
+ projectId,
138
+ cdnBase,
139
+ outputPath,
140
+ outputCssPath,
141
+ syncToken,
142
+ variablesOnly,
143
+ });
144
+ }
145
+ catch (error) {
146
+ console.error(`❌ Error: ${error.message || error}`);
147
+ process.exit(1);
148
+ }
149
+ }
133
150
  run();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strata-ds/core",
3
- "version": "2.1.16",
3
+ "version": "2.1.18",
4
4
  "type": "module",
5
5
  "description": "The runtime component library for Strata — design once, sync everywhere.",
6
6
  "homepage": "https://strata.charisol.io",
@@ -25,7 +25,8 @@
25
25
  "build": "rollup -c",
26
26
  "dev": "rollup -c -w",
27
27
  "build:css": "tailwindcss -i ./src/styles.css -o ./dist/styles.css --minify",
28
- "prepublishOnly": "npm run build"
28
+ "prepublishOnly": "npm run build",
29
+ "postinstall": "node -e \"if (require('fs').existsSync('./dist/cli/postinstall.js')) import('./dist/cli/postinstall.js')\""
29
30
  },
30
31
  "keywords": [
31
32
  "strata",