@flightdev/script 0.0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-2026 Flight Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,154 @@
1
+ # @flight-framework/script
2
+
3
+ Script loading optimization for improved Core Web Vitals.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @flight-framework/script
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```tsx
14
+ import { Script } from '@flight-framework/script/react';
15
+
16
+ function App() {
17
+ return (
18
+ <>
19
+ <Script
20
+ src="https://analytics.example.com/script.js"
21
+ strategy="afterInteractive"
22
+ />
23
+ </>
24
+ );
25
+ }
26
+ ```
27
+
28
+ ## Loading Strategies
29
+
30
+ | Strategy | When Loaded | Use Case |
31
+ |----------|-------------|----------|
32
+ | `beforeInteractive` | Before hydration | Critical polyfills |
33
+ | `afterInteractive` | After page is interactive | Analytics, tracking |
34
+ | `lazyOnload` | On browser idle | Widgets, chat |
35
+ | `worker` | In web worker | Heavy processing |
36
+
37
+ ## React Component
38
+
39
+ ```tsx
40
+ import { Script } from '@flight-framework/script/react';
41
+
42
+ // External script
43
+ <Script src="https://example.com/script.js" strategy="afterInteractive" />
44
+
45
+ // Inline script
46
+ <Script id="config">
47
+ {`window.CONFIG = { api: 'https://api.example.com' };`}
48
+ </Script>
49
+
50
+ // With callbacks
51
+ <Script
52
+ src="https://sdk.example.com/v1.js"
53
+ onLoad={() => window.SDK.init()}
54
+ onError={(e) => console.error(e)}
55
+ />
56
+ ```
57
+
58
+ ## useScript Hook
59
+
60
+ ```tsx
61
+ import { useScript } from '@flight-framework/script/react';
62
+
63
+ function Widget() {
64
+ const { loading, loaded, error } = useScript(
65
+ 'https://widget.example.com/sdk.js',
66
+ { strategy: 'lazyOnload' }
67
+ );
68
+
69
+ if (loading) return <div>Loading...</div>;
70
+ if (error) return <div>Failed to load</div>;
71
+ if (loaded) return <div id="widget" />;
72
+ return null;
73
+ }
74
+ ```
75
+
76
+ ## Props
77
+
78
+ | Prop | Type | Default | Description |
79
+ |------|------|---------|-------------|
80
+ | `src` | `string` | - | Script URL |
81
+ | `strategy` | `string` | `'afterInteractive'` | Loading strategy |
82
+ | `onLoad` | `function` | - | Load callback |
83
+ | `onError` | `function` | - | Error callback |
84
+ | `id` | `string` | - | Script ID |
85
+
86
+ ## Web Worker with Partytown
87
+
88
+ Move third-party scripts to a web worker for improved INP/FID:
89
+
90
+ ```bash
91
+ npm install @builder.io/partytown
92
+ ```
93
+
94
+ ### Configuration
95
+
96
+ ```typescript
97
+ import { partytown } from '@flight-framework/script/partytown';
98
+
99
+ const pt = partytown({
100
+ debug: process.env.NODE_ENV === 'development',
101
+ forward: ['dataLayer.push', 'gtag', 'fbq'],
102
+ autoDetect: true, // Auto-detect common analytics domains
103
+ });
104
+
105
+ // In your HTML head
106
+ // ${pt.headSnippet}
107
+ ```
108
+
109
+ ### Usage
110
+
111
+ ```tsx
112
+ import { Script } from '@flight-framework/script/react';
113
+
114
+ // Runs in Web Worker via Partytown
115
+ <Script
116
+ src="https://www.googletagmanager.com/gtag/js?id=G-XXX"
117
+ strategy="worker"
118
+ />
119
+
120
+ // Falls back gracefully if Partytown not installed
121
+ ```
122
+
123
+ ### Pre-configured Domains
124
+
125
+ The `autoDetect` option automatically moves scripts from these domains to the worker:
126
+
127
+ - Google Analytics, Tag Manager, Ads
128
+ - Facebook Pixel, LinkedIn, Twitter
129
+ - Segment, Amplitude, Heap, Mixpanel
130
+ - Intercom, Hotjar, Mouseflow
131
+ - Sentry, LogRocket, Clarity
132
+ - And 15+ more
133
+
134
+ ### Partytown API
135
+
136
+ ```typescript
137
+ import {
138
+ partytown,
139
+ isPartytownReady,
140
+ loadWithPartytown,
141
+ } from '@flight-framework/script/partytown';
142
+
143
+ // Check if Partytown is available
144
+ if (isPartytownReady()) {
145
+ // Partytown is loaded
146
+ }
147
+
148
+ // Load a script with Partytown (falls back if unavailable)
149
+ await loadWithPartytown('https://example.com/script.js');
150
+ ```
151
+
152
+ ## License
153
+
154
+ MIT
@@ -0,0 +1,155 @@
1
+ /**
2
+ * @flightdev/script - Partytown Adapter
3
+ *
4
+ * Move third-party scripts to a Web Worker for improved Core Web Vitals.
5
+ * This adapter integrates with @builder.io/partytown to offload scripts
6
+ * from the main thread.
7
+ *
8
+ * This is an OPTIONAL adapter. Install @builder.io/partytown only if you use it.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { partytown } from '@flightdev/script/partytown';
13
+ *
14
+ * // In your flight.config.ts or layout
15
+ * const config = partytown({
16
+ * debug: process.env.NODE_ENV === 'development',
17
+ * forward: ['dataLayer.push', 'gtag', 'fbq'],
18
+ * });
19
+ * ```
20
+ */
21
+ /**
22
+ * Partytown configuration options.
23
+ * These are passed directly to Partytown's configuration.
24
+ */
25
+ export interface PartytownConfig {
26
+ /**
27
+ * Enable debug mode with console logging.
28
+ * @default false
29
+ */
30
+ debug?: boolean;
31
+ /**
32
+ * Path to Partytown library files.
33
+ * @default '/~partytown/'
34
+ */
35
+ lib?: string;
36
+ /**
37
+ * Functions to forward from worker to main thread.
38
+ * Common examples: 'dataLayer.push', 'gtag', 'fbq'
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * forward: [
43
+ * 'dataLayer.push',
44
+ * 'gtag',
45
+ * 'fbq',
46
+ * 'plausible',
47
+ * '_paq.push',
48
+ * ]
49
+ * ```
50
+ */
51
+ forward?: string[];
52
+ /**
53
+ * Domains that should be proxied through the main thread.
54
+ * Required for scripts that don't support CORS.
55
+ */
56
+ proxyDomains?: string[];
57
+ /**
58
+ * Custom resolve function for script URLs.
59
+ * Use this to proxy third-party scripts through your server.
60
+ */
61
+ resolveUrl?: (url: URL, location: URL, type: string) => URL | string | null;
62
+ /**
63
+ * Load scripts synchronously (blocking).
64
+ * Only use for critical scripts.
65
+ * @default false
66
+ */
67
+ loadScriptsOnMainThread?: string[];
68
+ /**
69
+ * Sandbox iframe configuration.
70
+ */
71
+ sandbox?: {
72
+ /** Allow scripts from these origins */
73
+ allowedOrigins?: string[];
74
+ };
75
+ }
76
+ /**
77
+ * Partytown adapter options for Flight Framework.
78
+ */
79
+ export interface PartytownAdapterOptions extends PartytownConfig {
80
+ /**
81
+ * Enable the Partytown adapter.
82
+ * @default true
83
+ */
84
+ enabled?: boolean;
85
+ /**
86
+ * Auto-detect and transform analytics scripts.
87
+ * When true, common analytics scripts are automatically moved to worker.
88
+ * @default false
89
+ */
90
+ autoDetect?: boolean;
91
+ /**
92
+ * Known third-party domains to always run in worker.
93
+ */
94
+ knownDomains?: string[];
95
+ }
96
+ /**
97
+ * Result of Partytown adapter initialization.
98
+ */
99
+ export interface PartytownAdapterResult {
100
+ /** Whether Partytown is enabled */
101
+ enabled: boolean;
102
+ /** Configuration to pass to Partytown snippet */
103
+ config: PartytownConfig;
104
+ /** HTML snippet to inject in <head> */
105
+ headSnippet: string;
106
+ /** Check if a script should run in worker */
107
+ shouldRunInWorker: (src: string) => boolean;
108
+ /** Transform a script tag for Partytown */
109
+ transformScript: (src: string) => {
110
+ type: string;
111
+ src: string;
112
+ };
113
+ }
114
+ /**
115
+ * Create a Partytown adapter for Flight Framework.
116
+ *
117
+ * @param options - Partytown configuration options
118
+ * @returns Partytown adapter result with configuration and helpers
119
+ *
120
+ * @example
121
+ * ```typescript
122
+ * // Basic usage
123
+ * const pt = partytown({
124
+ * forward: ['dataLayer.push', 'gtag'],
125
+ * });
126
+ *
127
+ * // In your HTML head
128
+ * ${pt.headSnippet}
129
+ *
130
+ * // Transform scripts
131
+ * if (pt.shouldRunInWorker(scriptSrc)) {
132
+ * const { type, src } = pt.transformScript(scriptSrc);
133
+ * // Render: <script type="text/partytown" src={src} />
134
+ * }
135
+ * ```
136
+ */
137
+ export declare function partytown(options?: PartytownAdapterOptions): PartytownAdapterResult;
138
+ /**
139
+ * Generate inline Partytown snippet (for when async loading isn't possible).
140
+ * This should be used with the actual Partytown snippet content.
141
+ */
142
+ export declare function generateInlineSnippet(config: PartytownConfig): string;
143
+ /**
144
+ * Check if Partytown is available and initialized.
145
+ */
146
+ export declare function isPartytownReady(): boolean;
147
+ /**
148
+ * Dynamically load a script with Partytown.
149
+ * Falls back to normal loading if Partytown isn't available.
150
+ */
151
+ export declare function loadWithPartytown(src: string, options?: {
152
+ fallback?: boolean;
153
+ }): Promise<void>;
154
+ export default partytown;
155
+ //# sourceMappingURL=partytown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"partytown.d.ts","sourceRoot":"","sources":["../../src/adapters/partytown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAMH;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC5B;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAEnB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAExB;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,GAAG,GAAG,MAAM,GAAG,IAAI,CAAC;IAE5E;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;IAEnC;;OAEG;IACH,OAAO,CAAC,EAAE;QACN,uCAAuC;QACvC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;KAC7B,CAAC;CACL;AAED;;GAEG;AACH,MAAM,WAAW,uBAAwB,SAAQ,eAAe;IAC5D;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACnC,mCAAmC;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,iDAAiD;IACjD,MAAM,EAAE,eAAe,CAAC;IACxB,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,iBAAiB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IAC5C,2CAA2C;IAC3C,eAAe,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CACnE;AA8CD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,SAAS,CAAC,OAAO,GAAE,uBAA4B,GAAG,sBAAsB,CAmFvF;AA2CD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAWrE;AAMD;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAG1C;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC7B,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAO,GACrC,OAAO,CAAC,IAAI,CAAC,CA0Bf;AAMD,eAAe,SAAS,CAAC"}
@@ -0,0 +1,242 @@
1
+ /**
2
+ * @flightdev/script - Partytown Adapter
3
+ *
4
+ * Move third-party scripts to a Web Worker for improved Core Web Vitals.
5
+ * This adapter integrates with @builder.io/partytown to offload scripts
6
+ * from the main thread.
7
+ *
8
+ * This is an OPTIONAL adapter. Install @builder.io/partytown only if you use it.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { partytown } from '@flightdev/script/partytown';
13
+ *
14
+ * // In your flight.config.ts or layout
15
+ * const config = partytown({
16
+ * debug: process.env.NODE_ENV === 'development',
17
+ * forward: ['dataLayer.push', 'gtag', 'fbq'],
18
+ * });
19
+ * ```
20
+ */
21
+ // ============================================================================
22
+ // Known Third-Party Domains
23
+ // ============================================================================
24
+ /**
25
+ * Pre-configured domains known to work with Partytown.
26
+ * These scripts are safe to move to a web worker.
27
+ */
28
+ const DEFAULT_KNOWN_DOMAINS = [
29
+ 'google-analytics.com',
30
+ 'googletagmanager.com',
31
+ 'connect.facebook.net',
32
+ 'www.googleadservices.com',
33
+ 'googleads.g.doubleclick.net',
34
+ 'snap.licdn.com',
35
+ 'static.ads-twitter.com',
36
+ 'analytics.tiktok.com',
37
+ 'plausible.io',
38
+ 'cdn.segment.com',
39
+ 'js.hs-scripts.com',
40
+ 'js.hs-analytics.net',
41
+ 'cdn.amplitude.com',
42
+ 'cdn.heapanalytics.com',
43
+ 'cdn.mxpnl.com',
44
+ 'js.intercomcdn.com',
45
+ 'widget.intercom.io',
46
+ 'static.hotjar.com',
47
+ 'cdn.mouseflow.com',
48
+ 'cdn.logrocket.io',
49
+ 'js.sentry-cdn.com',
50
+ 'browser.sentry-cdn.com',
51
+ 'cdn.clarity.ms',
52
+ 'static.klaviyo.com',
53
+ 'js.driftt.com',
54
+ 'widget.crisp.chat',
55
+ 'embed.typeform.com',
56
+ 'player.vimeo.com',
57
+ 'www.youtube.com',
58
+ ];
59
+ // ============================================================================
60
+ // Partytown Adapter
61
+ // ============================================================================
62
+ /**
63
+ * Create a Partytown adapter for Flight Framework.
64
+ *
65
+ * @param options - Partytown configuration options
66
+ * @returns Partytown adapter result with configuration and helpers
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * // Basic usage
71
+ * const pt = partytown({
72
+ * forward: ['dataLayer.push', 'gtag'],
73
+ * });
74
+ *
75
+ * // In your HTML head
76
+ * ${pt.headSnippet}
77
+ *
78
+ * // Transform scripts
79
+ * if (pt.shouldRunInWorker(scriptSrc)) {
80
+ * const { type, src } = pt.transformScript(scriptSrc);
81
+ * // Render: <script type="text/partytown" src={src} />
82
+ * }
83
+ * ```
84
+ */
85
+ export function partytown(options = {}) {
86
+ const { enabled = true, debug = false, lib = '/~partytown/', forward = [], proxyDomains = [], autoDetect = false, knownDomains = [], loadScriptsOnMainThread = [], resolveUrl, sandbox, } = options;
87
+ // Merge known domains with user-provided domains
88
+ const allKnownDomains = autoDetect
89
+ ? [...DEFAULT_KNOWN_DOMAINS, ...knownDomains]
90
+ : knownDomains;
91
+ // Build Partytown configuration object
92
+ const config = {
93
+ debug,
94
+ lib,
95
+ forward,
96
+ loadScriptsOnMainThread,
97
+ };
98
+ if (resolveUrl) {
99
+ config.resolveUrl = resolveUrl;
100
+ }
101
+ if (sandbox) {
102
+ config.sandbox = sandbox;
103
+ }
104
+ // Generate head snippet for SSR
105
+ const headSnippet = generateHeadSnippet(config, proxyDomains);
106
+ // Helper to check if script should run in worker
107
+ const shouldRunInWorker = (src) => {
108
+ if (!enabled)
109
+ return false;
110
+ if (!src)
111
+ return false;
112
+ try {
113
+ const url = new URL(src, 'https://example.com');
114
+ const hostname = url.hostname.toLowerCase();
115
+ // Check against known domains
116
+ for (const domain of allKnownDomains) {
117
+ if (hostname.includes(domain)) {
118
+ return true;
119
+ }
120
+ }
121
+ // Check against proxy domains
122
+ for (const domain of proxyDomains) {
123
+ if (hostname.includes(domain)) {
124
+ return true;
125
+ }
126
+ }
127
+ }
128
+ catch {
129
+ // Invalid URL, don't transform
130
+ return false;
131
+ }
132
+ return false;
133
+ };
134
+ // Helper to transform script tag attributes
135
+ const transformScript = (src) => {
136
+ return {
137
+ type: 'text/partytown',
138
+ src,
139
+ };
140
+ };
141
+ return {
142
+ enabled,
143
+ config,
144
+ headSnippet,
145
+ shouldRunInWorker,
146
+ transformScript,
147
+ };
148
+ }
149
+ // ============================================================================
150
+ // Helper Functions
151
+ // ============================================================================
152
+ /**
153
+ * Generate the Partytown head snippet for SSR.
154
+ */
155
+ function generateHeadSnippet(config, proxyDomains) {
156
+ const configJson = JSON.stringify({
157
+ debug: config.debug,
158
+ lib: config.lib,
159
+ forward: config.forward,
160
+ });
161
+ // Generate resolve URL function if proxy domains are specified
162
+ let resolveUrlScript = '';
163
+ if (proxyDomains.length > 0) {
164
+ const domainChecks = proxyDomains
165
+ .map(d => `url.hostname.includes('${d}')`)
166
+ .join(' || ');
167
+ resolveUrlScript = `
168
+ resolveUrl: function(url, location, type) {
169
+ if (${domainChecks}) {
170
+ var proxyUrl = new URL('/_flight/proxy');
171
+ proxyUrl.searchParams.set('url', url.href);
172
+ return proxyUrl;
173
+ }
174
+ return url;
175
+ },`;
176
+ }
177
+ return `
178
+ <!-- Partytown Configuration (Flight Framework) -->
179
+ <script>
180
+ partytown = ${configJson.slice(0, -1)}${resolveUrlScript}};
181
+ </script>
182
+ <script src="${config.lib}partytown.js" async></script>
183
+ `.trim();
184
+ }
185
+ /**
186
+ * Generate inline Partytown snippet (for when async loading isn't possible).
187
+ * This should be used with the actual Partytown snippet content.
188
+ */
189
+ export function generateInlineSnippet(config) {
190
+ return `
191
+ <script>
192
+ /* Partytown Config */
193
+ partytown = {
194
+ debug: ${config.debug || false},
195
+ lib: '${config.lib || '/~partytown/'}',
196
+ forward: ${JSON.stringify(config.forward || [])}
197
+ };
198
+ </script>
199
+ `.trim();
200
+ }
201
+ // ============================================================================
202
+ // React Hook (for client-side initialization)
203
+ // ============================================================================
204
+ /**
205
+ * Check if Partytown is available and initialized.
206
+ */
207
+ export function isPartytownReady() {
208
+ if (typeof window === 'undefined')
209
+ return false;
210
+ return typeof window.partytown !== 'undefined';
211
+ }
212
+ /**
213
+ * Dynamically load a script with Partytown.
214
+ * Falls back to normal loading if Partytown isn't available.
215
+ */
216
+ export function loadWithPartytown(src, options = {}) {
217
+ const { fallback = true } = options;
218
+ return new Promise((resolve, reject) => {
219
+ if (typeof document === 'undefined') {
220
+ resolve();
221
+ return;
222
+ }
223
+ const script = document.createElement('script');
224
+ if (isPartytownReady()) {
225
+ script.type = 'text/partytown';
226
+ }
227
+ else if (!fallback) {
228
+ reject(new Error('Partytown not available and fallback disabled'));
229
+ return;
230
+ }
231
+ script.src = src;
232
+ script.async = true;
233
+ script.onload = () => resolve();
234
+ script.onerror = () => reject(new Error(`Failed to load: ${src}`));
235
+ document.head.appendChild(script);
236
+ });
237
+ }
238
+ // ============================================================================
239
+ // Exports
240
+ // ============================================================================
241
+ export default partytown;
242
+ //# sourceMappingURL=partytown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"partytown.js","sourceRoot":"","sources":["../../src/adapters/partytown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * @flightdev/script/react - React Script Component
3
+ *
4
+ * React component for optimized script loading.
5
+ */
6
+ import React from 'react';
7
+ import { type ScriptOptions, type ScriptState } from '../index.js';
8
+ export interface ScriptProps extends ScriptOptions {
9
+ /** Script source URL (required unless using dangerouslySetInnerHTML) */
10
+ src?: string;
11
+ /** Children for inline scripts */
12
+ children?: string;
13
+ }
14
+ /**
15
+ * Optimized script loading component
16
+ *
17
+ * @example
18
+ * ```tsx
19
+ * import { Script } from '@flightdev/script/react';
20
+ *
21
+ * // External script with afterInteractive strategy (default)
22
+ * <Script src="https://analytics.example.com/script.js" />
23
+ *
24
+ * // Lazy load for non-critical scripts
25
+ * <Script
26
+ * src="https://widget.example.com/embed.js"
27
+ * strategy="lazyOnload"
28
+ * onLoad={() => console.log('Widget loaded!')}
29
+ * />
30
+ *
31
+ * // Inline script
32
+ * <Script id="my-inline-script">
33
+ * {`console.log('Hello from inline script!')`}
34
+ * </Script>
35
+ *
36
+ * // Critical script (blocks hydration)
37
+ * <Script
38
+ * src="/critical.js"
39
+ * strategy="beforeInteractive"
40
+ * />
41
+ * ```
42
+ */
43
+ export declare function Script({ src, children, dangerouslySetInnerHTML, strategy, onLoad, onError, onReady, id, async: asyncAttr, defer, type, nonce, ...rest }: ScriptProps): React.ReactElement | null;
44
+ /**
45
+ * Hook to load and track script state
46
+ *
47
+ * @example
48
+ * ```tsx
49
+ * import { useScript } from '@flightdev/script/react';
50
+ *
51
+ * function WidgetComponent() {
52
+ * const { loaded, loading, error } = useScript(
53
+ * 'https://widget.example.com/sdk.js',
54
+ * { strategy: 'lazyOnload' }
55
+ * );
56
+ *
57
+ * if (loading) return <div>Loading widget...</div>;
58
+ * if (error) return <div>Failed to load widget</div>;
59
+ * if (loaded) return <div id="widget-container" />;
60
+ * return null;
61
+ * }
62
+ * ```
63
+ */
64
+ export declare function useScript(src: string, options?: Omit<ScriptOptions, 'src' | 'dangerouslySetInnerHTML'>): ScriptState;
65
+ export interface ScriptProviderProps {
66
+ /** Scripts to preload/preconnect */
67
+ scripts?: Array<{
68
+ src: string;
69
+ preconnect?: boolean;
70
+ preload?: boolean;
71
+ }>;
72
+ children: React.ReactNode;
73
+ }
74
+ /**
75
+ * Provider for script preloading hints
76
+ *
77
+ * @example
78
+ * ```tsx
79
+ * import { ScriptProvider } from '@flightdev/script/react';
80
+ *
81
+ * function App() {
82
+ * return (
83
+ * <ScriptProvider
84
+ * scripts={[
85
+ * { src: 'https://analytics.example.com', preconnect: true },
86
+ * { src: 'https://cdn.example.com/sdk.js', preload: true },
87
+ * ]}
88
+ * >
89
+ * <MyApp />
90
+ * </ScriptProvider>
91
+ * );
92
+ * }
93
+ * ```
94
+ */
95
+ export declare function ScriptProvider({ scripts, children }: ScriptProviderProps): React.ReactElement;
96
+ export { loadScript, preconnect, dnsPrefetch, preloadScript, isScriptLoaded, waitForScript } from '../index.js';
97
+ export type { ScriptOptions, ScriptStrategy, ScriptState } from '../index.js';
98
+ //# sourceMappingURL=react.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../src/components/react.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAA2C,MAAM,OAAO,CAAC;AAChE,OAAO,EAEH,KAAK,aAAa,EAElB,KAAK,WAAW,EACnB,MAAM,aAAa,CAAC;AAMrB,MAAM,WAAW,WAAY,SAAQ,aAAa;IAC9C,wEAAwE;IACxE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,MAAM,CAAC,EACnB,GAAG,EACH,QAAQ,EACR,uBAAuB,EACvB,QAA6B,EAC7B,MAAM,EACN,OAAO,EACP,OAAO,EACP,EAAE,EACF,KAAK,EAAE,SAAS,EAChB,KAAK,EACL,IAAI,EACJ,KAAK,EACL,GAAG,IAAI,EACV,EAAE,WAAW,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CAsEzC;AAMD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,SAAS,CACrB,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,aAAa,EAAE,KAAK,GAAG,yBAAyB,CAAM,GACrE,WAAW,CA8Bb;AAMD,MAAM,WAAW,mBAAmB;IAChC,oCAAoC;IACpC,OAAO,CAAC,EAAE,KAAK,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,OAAO,CAAC,EAAE,OAAO,CAAC;KACrB,CAAC,CAAC;IACH,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,cAAc,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,mBAAmB,GAAG,KAAK,CAAC,YAAY,CAwB7F;AAMD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAChH,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,172 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * @flightdev/script/react - React Script Component
4
+ *
5
+ * React component for optimized script loading.
6
+ */
7
+ import React, { useEffect, useState } from 'react';
8
+ import { loadScript } from '../index.js';
9
+ /**
10
+ * Optimized script loading component
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * import { Script } from '@flightdev/script/react';
15
+ *
16
+ * // External script with afterInteractive strategy (default)
17
+ * <Script src="https://analytics.example.com/script.js" />
18
+ *
19
+ * // Lazy load for non-critical scripts
20
+ * <Script
21
+ * src="https://widget.example.com/embed.js"
22
+ * strategy="lazyOnload"
23
+ * onLoad={() => console.log('Widget loaded!')}
24
+ * />
25
+ *
26
+ * // Inline script
27
+ * <Script id="my-inline-script">
28
+ * {`console.log('Hello from inline script!')`}
29
+ * </Script>
30
+ *
31
+ * // Critical script (blocks hydration)
32
+ * <Script
33
+ * src="/critical.js"
34
+ * strategy="beforeInteractive"
35
+ * />
36
+ * ```
37
+ */
38
+ export function Script({ src, children, dangerouslySetInnerHTML, strategy = 'afterInteractive', onLoad, onError, onReady, id, async: asyncAttr, defer, type, nonce, ...rest }) {
39
+ const [loaded, setLoaded] = useState(false);
40
+ useEffect(() => {
41
+ // Handle inline scripts
42
+ if (!src && (children || dangerouslySetInnerHTML)) {
43
+ const script = document.createElement('script');
44
+ if (id)
45
+ script.id = id;
46
+ if (type)
47
+ script.type = type;
48
+ if (nonce)
49
+ script.nonce = nonce;
50
+ // Add data attributes
51
+ Object.entries(rest).forEach(([key, value]) => {
52
+ if (key.startsWith('data-') && value) {
53
+ script.setAttribute(key, value);
54
+ }
55
+ });
56
+ script.textContent = children || dangerouslySetInnerHTML?.__html || '';
57
+ document.body.appendChild(script);
58
+ setLoaded(true);
59
+ onLoad?.();
60
+ onReady?.();
61
+ return () => {
62
+ script.remove();
63
+ };
64
+ }
65
+ // Handle external scripts
66
+ if (src) {
67
+ onReady?.();
68
+ loadScript(src, {
69
+ strategy,
70
+ onLoad: () => {
71
+ setLoaded(true);
72
+ onLoad?.();
73
+ },
74
+ onError,
75
+ id,
76
+ async: asyncAttr,
77
+ defer,
78
+ type,
79
+ nonce,
80
+ ...rest,
81
+ }).catch((error) => {
82
+ onError?.(error instanceof Error ? error : new Error(String(error)));
83
+ });
84
+ }
85
+ }, [src, strategy, id]);
86
+ // For SSR/beforeInteractive, render the script tag directly
87
+ if (strategy === 'beforeInteractive' && src) {
88
+ return (_jsx("script", { src: src, id: id, async: asyncAttr, defer: defer, type: type, nonce: nonce, ...rest }));
89
+ }
90
+ // For other strategies, we load via useEffect (no SSR output)
91
+ return null;
92
+ }
93
+ // ============================================================================
94
+ // useScript Hook
95
+ // ============================================================================
96
+ /**
97
+ * Hook to load and track script state
98
+ *
99
+ * @example
100
+ * ```tsx
101
+ * import { useScript } from '@flightdev/script/react';
102
+ *
103
+ * function WidgetComponent() {
104
+ * const { loaded, loading, error } = useScript(
105
+ * 'https://widget.example.com/sdk.js',
106
+ * { strategy: 'lazyOnload' }
107
+ * );
108
+ *
109
+ * if (loading) return <div>Loading widget...</div>;
110
+ * if (error) return <div>Failed to load widget</div>;
111
+ * if (loaded) return <div id="widget-container" />;
112
+ * return null;
113
+ * }
114
+ * ```
115
+ */
116
+ export function useScript(src, options = {}) {
117
+ const [state, setState] = useState({
118
+ loading: true,
119
+ loaded: false,
120
+ error: null,
121
+ });
122
+ useEffect(() => {
123
+ setState({ loading: true, loaded: false, error: null });
124
+ loadScript(src, {
125
+ ...options,
126
+ onLoad: () => {
127
+ setState({ loading: false, loaded: true, error: null });
128
+ options.onLoad?.();
129
+ },
130
+ onError: (error) => {
131
+ setState({ loading: false, loaded: false, error });
132
+ options.onError?.(error);
133
+ },
134
+ }).catch((error) => {
135
+ setState({
136
+ loading: false,
137
+ loaded: false,
138
+ error: error instanceof Error ? error : new Error(String(error))
139
+ });
140
+ });
141
+ }, [src, options.strategy]);
142
+ return state;
143
+ }
144
+ /**
145
+ * Provider for script preloading hints
146
+ *
147
+ * @example
148
+ * ```tsx
149
+ * import { ScriptProvider } from '@flightdev/script/react';
150
+ *
151
+ * function App() {
152
+ * return (
153
+ * <ScriptProvider
154
+ * scripts={[
155
+ * { src: 'https://analytics.example.com', preconnect: true },
156
+ * { src: 'https://cdn.example.com/sdk.js', preload: true },
157
+ * ]}
158
+ * >
159
+ * <MyApp />
160
+ * </ScriptProvider>
161
+ * );
162
+ * }
163
+ * ```
164
+ */
165
+ export function ScriptProvider({ scripts, children }) {
166
+ return (_jsxs(_Fragment, { children: [scripts?.map((script, i) => (_jsxs(React.Fragment, { children: [script.preconnect && (_jsx("link", { rel: "preconnect", href: new URL(script.src).origin, crossOrigin: "anonymous" })), script.preload && (_jsx("link", { rel: "preload", href: script.src, as: "script" }))] }, i))), children] }));
167
+ }
168
+ // ============================================================================
169
+ // Re-exports
170
+ // ============================================================================
171
+ export { loadScript, preconnect, dnsPrefetch, preloadScript, isScriptLoaded, waitForScript } from '../index.js';
172
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.js","sourceRoot":"","sources":["../../src/components/react.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * @flightdev/script - Agnostic Script Loading Optimization
3
+ *
4
+ * Control how third-party scripts load to improve Core Web Vitals.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { Script } from '@flightdev/script/react';
9
+ *
10
+ * // Load analytics after page is interactive
11
+ * <Script
12
+ * src="https://analytics.example.com/script.js"
13
+ * strategy="afterInteractive"
14
+ * />
15
+ *
16
+ * // Lazy load when visible
17
+ * <Script
18
+ * src="https://widget.example.com/embed.js"
19
+ * strategy="lazyOnload"
20
+ * />
21
+ * ```
22
+ */
23
+ /**
24
+ * Script loading strategy
25
+ *
26
+ * - `beforeInteractive`: Load immediately, blocks hydration (use sparingly)
27
+ * - `afterInteractive`: Load after page is interactive (default)
28
+ * - `lazyOnload`: Load when browser is idle or on scroll
29
+ * - `worker`: Load in a web worker (experimental)
30
+ */
31
+ export type ScriptStrategy = 'beforeInteractive' | 'afterInteractive' | 'lazyOnload' | 'worker';
32
+ /**
33
+ * Script loading options
34
+ */
35
+ export interface ScriptOptions {
36
+ /** Script source URL */
37
+ src?: string;
38
+ /** Inline script content */
39
+ dangerouslySetInnerHTML?: {
40
+ __html: string;
41
+ };
42
+ /** Loading strategy */
43
+ strategy?: ScriptStrategy;
44
+ /** Called when script loads */
45
+ onLoad?: () => void;
46
+ /** Called on script error */
47
+ onError?: (error: Error) => void;
48
+ /** Called before script loads */
49
+ onReady?: () => void;
50
+ /** Script ID for deduplication */
51
+ id?: string;
52
+ /** Async attribute */
53
+ async?: boolean;
54
+ /** Defer attribute */
55
+ defer?: boolean;
56
+ /** Module script */
57
+ type?: 'module' | 'text/javascript';
58
+ /** Nonce for CSP */
59
+ nonce?: string;
60
+ /** data-* attributes */
61
+ [key: `data-${string}`]: string | undefined;
62
+ }
63
+ /**
64
+ * Script state
65
+ */
66
+ export interface ScriptState {
67
+ loading: boolean;
68
+ loaded: boolean;
69
+ error: Error | null;
70
+ }
71
+ /**
72
+ * Load a script programmatically
73
+ */
74
+ export declare function loadScript(src: string, options?: Omit<ScriptOptions, 'src' | 'dangerouslySetInnerHTML'>): Promise<void>;
75
+ /**
76
+ * Preconnect to a domain for faster script loading
77
+ */
78
+ export declare function preconnect(url: string, options?: {
79
+ crossOrigin?: boolean;
80
+ }): void;
81
+ /**
82
+ * DNS prefetch for a domain
83
+ */
84
+ export declare function dnsPrefetch(url: string): void;
85
+ /**
86
+ * Preload a script without executing
87
+ */
88
+ export declare function preloadScript(src: string, options?: {
89
+ as?: 'script';
90
+ }): void;
91
+ /**
92
+ * Check if a script is already loaded
93
+ */
94
+ export declare function isScriptLoaded(src: string): boolean;
95
+ /**
96
+ * Wait for a script to load
97
+ */
98
+ export declare function waitForScript(src: string): Promise<void>;
99
+ export type { ScriptOptions as Options, ScriptStrategy as Strategy };
100
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAMH;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GACpB,mBAAmB,GACnB,kBAAkB,GAClB,YAAY,GACZ,QAAQ,CAAC;AAEf;;GAEG;AACH,MAAM,WAAW,aAAa;IAC1B,wBAAwB;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,uBAAuB,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,uBAAuB;IACvB,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,+BAA+B;IAC/B,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,6BAA6B;IAC7B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,kCAAkC;IAClC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,sBAAsB;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,sBAAsB;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,oBAAoB;IACpB,IAAI,CAAC,EAAE,QAAQ,GAAG,iBAAiB,CAAC;IACpC,oBAAoB;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wBAAwB;IACxB,CAAC,GAAG,EAAE,QAAQ,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAC;CAC/C;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACvB;AASD;;GAEG;AACH,wBAAsB,UAAU,CAC5B,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,aAAa,EAAE,KAAK,GAAG,yBAAyB,CAAM,GACrE,OAAO,CAAC,IAAI,CAAC,CAyKf;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,IAAI,CAUrF;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAO7C;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,EAAE,CAAC,EAAE,QAAQ,CAAA;CAAO,GAAG,IAAI,CAQhF;AAMD;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQxD;AAMD,YAAY,EAAE,aAAa,IAAI,OAAO,EAAE,cAAc,IAAI,QAAQ,EAAE,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,240 @@
1
+ /**
2
+ * @flightdev/script - Agnostic Script Loading Optimization
3
+ *
4
+ * Control how third-party scripts load to improve Core Web Vitals.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { Script } from '@flightdev/script/react';
9
+ *
10
+ * // Load analytics after page is interactive
11
+ * <Script
12
+ * src="https://analytics.example.com/script.js"
13
+ * strategy="afterInteractive"
14
+ * />
15
+ *
16
+ * // Lazy load when visible
17
+ * <Script
18
+ * src="https://widget.example.com/embed.js"
19
+ * strategy="lazyOnload"
20
+ * />
21
+ * ```
22
+ */
23
+ // ============================================================================
24
+ // Script Loader
25
+ // ============================================================================
26
+ const loadedScripts = new Set();
27
+ const loadingScripts = new Map();
28
+ /**
29
+ * Load a script programmatically
30
+ */
31
+ export async function loadScript(src, options = {}) {
32
+ const { strategy = 'afterInteractive', onLoad, onError, id, async: asyncAttr = true, defer, type, nonce, ...dataAttrs } = options;
33
+ const scriptId = id || src;
34
+ // Already loaded
35
+ if (loadedScripts.has(scriptId)) {
36
+ onLoad?.();
37
+ return;
38
+ }
39
+ // Currently loading
40
+ if (loadingScripts.has(scriptId)) {
41
+ return loadingScripts.get(scriptId);
42
+ }
43
+ const loadPromise = new Promise((resolve, reject) => {
44
+ const executeLoad = () => {
45
+ const script = document.createElement('script');
46
+ script.src = src;
47
+ if (id)
48
+ script.id = id;
49
+ if (asyncAttr)
50
+ script.async = true;
51
+ if (defer)
52
+ script.defer = true;
53
+ if (type)
54
+ script.type = type;
55
+ if (nonce)
56
+ script.nonce = nonce;
57
+ // Add data attributes
58
+ Object.entries(dataAttrs).forEach(([key, value]) => {
59
+ if (key.startsWith('data-') && typeof value === 'string') {
60
+ script.setAttribute(key, value);
61
+ }
62
+ });
63
+ script.onload = () => {
64
+ loadedScripts.add(scriptId);
65
+ loadingScripts.delete(scriptId);
66
+ onLoad?.();
67
+ resolve();
68
+ };
69
+ script.onerror = () => {
70
+ loadingScripts.delete(scriptId);
71
+ const error = new Error(`Failed to load script: ${src}`);
72
+ onError?.(error);
73
+ reject(error);
74
+ };
75
+ document.body.appendChild(script);
76
+ };
77
+ // Apply loading strategy
78
+ switch (strategy) {
79
+ case 'beforeInteractive':
80
+ // Load immediately
81
+ executeLoad();
82
+ break;
83
+ case 'afterInteractive':
84
+ // Wait for DOM to be ready
85
+ if (document.readyState === 'complete' || document.readyState === 'interactive') {
86
+ executeLoad();
87
+ }
88
+ else {
89
+ document.addEventListener('DOMContentLoaded', executeLoad, { once: true });
90
+ }
91
+ break;
92
+ case 'lazyOnload':
93
+ // Wait for window load or use requestIdleCallback
94
+ if (document.readyState === 'complete') {
95
+ if ('requestIdleCallback' in window) {
96
+ requestIdleCallback(executeLoad, { timeout: 5000 });
97
+ }
98
+ else {
99
+ setTimeout(executeLoad, 1);
100
+ }
101
+ }
102
+ else {
103
+ window.addEventListener('load', () => {
104
+ if ('requestIdleCallback' in window) {
105
+ requestIdleCallback(executeLoad, { timeout: 5000 });
106
+ }
107
+ else {
108
+ setTimeout(executeLoad, 1);
109
+ }
110
+ }, { once: true });
111
+ }
112
+ break;
113
+ case 'worker':
114
+ // Web Worker strategy using Partytown
115
+ // Creates script with type="text/partytown" for Partytown to pick up
116
+ const executeWorkerLoad = () => {
117
+ const script = document.createElement('script');
118
+ script.src = src;
119
+ // Check if Partytown is available
120
+ const hasPartytown = typeof window.partytown !== 'undefined';
121
+ if (hasPartytown) {
122
+ // Use Partytown - script runs in web worker
123
+ script.type = 'text/partytown';
124
+ }
125
+ else {
126
+ // Fallback to async loading on main thread
127
+ script.async = true;
128
+ console.info('[flight-script] Partytown not available, loading on main thread:', src);
129
+ }
130
+ if (id)
131
+ script.id = id;
132
+ if (nonce)
133
+ script.nonce = nonce;
134
+ // Add data attributes
135
+ Object.entries(dataAttrs).forEach(([key, value]) => {
136
+ if (key.startsWith('data-') && typeof value === 'string') {
137
+ script.setAttribute(key, value);
138
+ }
139
+ });
140
+ script.onload = () => {
141
+ loadedScripts.add(scriptId);
142
+ loadingScripts.delete(scriptId);
143
+ onLoad?.();
144
+ resolve();
145
+ };
146
+ script.onerror = () => {
147
+ loadingScripts.delete(scriptId);
148
+ const error = new Error(`Failed to load script: ${src}`);
149
+ onError?.(error);
150
+ reject(error);
151
+ };
152
+ // Insert after Partytown script if available
153
+ const partytownScript = document.querySelector('script[src*="partytown"]');
154
+ if (partytownScript && partytownScript.parentNode) {
155
+ partytownScript.parentNode.insertBefore(script, partytownScript.nextSibling);
156
+ }
157
+ else {
158
+ document.head.appendChild(script);
159
+ }
160
+ // If using Partytown, the script is handled by the worker
161
+ // Consider it loaded immediately for our tracking
162
+ if (hasPartytown) {
163
+ loadedScripts.add(scriptId);
164
+ loadingScripts.delete(scriptId);
165
+ onLoad?.();
166
+ resolve();
167
+ }
168
+ };
169
+ // Wait for DOM ready before adding worker scripts
170
+ if (document.readyState === 'complete' || document.readyState === 'interactive') {
171
+ executeWorkerLoad();
172
+ }
173
+ else {
174
+ document.addEventListener('DOMContentLoaded', executeWorkerLoad, { once: true });
175
+ }
176
+ break;
177
+ }
178
+ });
179
+ loadingScripts.set(scriptId, loadPromise);
180
+ return loadPromise;
181
+ }
182
+ /**
183
+ * Preconnect to a domain for faster script loading
184
+ */
185
+ export function preconnect(url, options = {}) {
186
+ if (typeof document === 'undefined')
187
+ return;
188
+ const link = document.createElement('link');
189
+ link.rel = 'preconnect';
190
+ link.href = new URL(url).origin;
191
+ if (options.crossOrigin) {
192
+ link.crossOrigin = 'anonymous';
193
+ }
194
+ document.head.appendChild(link);
195
+ }
196
+ /**
197
+ * DNS prefetch for a domain
198
+ */
199
+ export function dnsPrefetch(url) {
200
+ if (typeof document === 'undefined')
201
+ return;
202
+ const link = document.createElement('link');
203
+ link.rel = 'dns-prefetch';
204
+ link.href = new URL(url).origin;
205
+ document.head.appendChild(link);
206
+ }
207
+ /**
208
+ * Preload a script without executing
209
+ */
210
+ export function preloadScript(src, options = {}) {
211
+ if (typeof document === 'undefined')
212
+ return;
213
+ const link = document.createElement('link');
214
+ link.rel = 'preload';
215
+ link.as = options.as || 'script';
216
+ link.href = src;
217
+ document.head.appendChild(link);
218
+ }
219
+ // ============================================================================
220
+ // Utilities
221
+ // ============================================================================
222
+ /**
223
+ * Check if a script is already loaded
224
+ */
225
+ export function isScriptLoaded(src) {
226
+ return loadedScripts.has(src);
227
+ }
228
+ /**
229
+ * Wait for a script to load
230
+ */
231
+ export function waitForScript(src) {
232
+ if (loadedScripts.has(src)) {
233
+ return Promise.resolve();
234
+ }
235
+ if (loadingScripts.has(src)) {
236
+ return loadingScripts.get(src);
237
+ }
238
+ return loadScript(src);
239
+ }
240
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@flightdev/script",
3
+ "version": "0.0.2",
4
+ "description": "Agnostic script loading optimization with multiple strategies",
5
+ "type": "module",
6
+ "files": [
7
+ "dist"
8
+ ],
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ },
14
+ "./react": {
15
+ "types": "./dist/components/react.d.ts",
16
+ "import": "./dist/components/react.js"
17
+ },
18
+ "./partytown": {
19
+ "types": "./dist/adapters/partytown.d.ts",
20
+ "import": "./dist/adapters/partytown.js"
21
+ }
22
+ },
23
+ "keywords": [
24
+ "flight",
25
+ "script",
26
+ "optimization",
27
+ "lazy-loading",
28
+ "defer",
29
+ "async",
30
+ "partytown",
31
+ "web-worker"
32
+ ],
33
+ "author": "",
34
+ "license": "MIT",
35
+ "peerDependencies": {
36
+ "react": ">=18.0.0",
37
+ "@builder.io/partytown": ">=0.10.0"
38
+ },
39
+ "peerDependenciesMeta": {
40
+ "react": {
41
+ "optional": true
42
+ },
43
+ "@builder.io/partytown": {
44
+ "optional": true
45
+ }
46
+ },
47
+ "devDependencies": {
48
+ "@types/node": "^22.10.1",
49
+ "@types/react": "^19.0.6",
50
+ "typescript": "^5.7.2"
51
+ },
52
+ "scripts": {
53
+ "build": "tsc",
54
+ "dev": "tsc --watch"
55
+ }
56
+ }