securenow 6.0.2 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONSUMING-APPS-GUIDE.md +455 -0
- package/NPM_README.md +2029 -0
- package/README.md +297 -40
- package/SKILL-API.md +634 -0
- package/SKILL-CLI.md +454 -0
- package/cidr.js +83 -0
- package/cli/apps.js +585 -0
- package/cli/auth.js +280 -0
- package/cli/client.js +115 -0
- package/cli/config.js +173 -0
- package/cli/diagnostics.js +387 -0
- package/cli/firewall.js +100 -0
- package/cli/fp.js +638 -0
- package/cli/init.js +201 -0
- package/cli/monitor.js +440 -0
- package/cli/run.js +148 -0
- package/cli/security.js +980 -0
- package/cli/ui.js +386 -0
- package/cli/utils.js +127 -0
- package/cli.js +466 -455
- package/console-instrumentation.js +147 -136
- package/docs/ALL-FRAMEWORKS-QUICKSTART.md +1377 -455
- package/docs/API-KEYS-GUIDE.md +233 -0
- package/docs/ARCHITECTURE.md +3 -3
- package/docs/AUTO-BODY-CAPTURE.md +1 -1
- package/docs/AUTO-SETUP-SUMMARY.md +331 -0
- package/docs/AUTO-SETUP.md +4 -4
- package/docs/AUTOMATIC-IP-CAPTURE.md +5 -5
- package/docs/BODY-CAPTURE-FIX.md +261 -0
- package/docs/BODY-CAPTURE-QUICKSTART.md +2 -2
- package/docs/CHANGELOG-NEXTJS.md +1 -35
- package/docs/COMPLETION-REPORT.md +408 -0
- package/docs/CUSTOMER-GUIDE.md +16 -16
- package/docs/EASIEST-SETUP.md +5 -5
- package/docs/ENVIRONMENT-VARIABLES.md +880 -652
- package/docs/EXPRESS-BODY-CAPTURE.md +13 -12
- package/docs/EXPRESS-SETUP-GUIDE.md +719 -720
- package/docs/FINAL-SOLUTION.md +335 -0
- package/docs/FIREWALL-GUIDE.md +426 -0
- package/docs/IMPLEMENTATION-SUMMARY.md +410 -0
- package/docs/INDEX.md +22 -4
- package/docs/LOGGING-GUIDE.md +701 -708
- package/docs/LOGGING-QUICKSTART.md +234 -255
- package/docs/NEXTJS-BODY-CAPTURE-COMPARISON.md +323 -0
- package/docs/NEXTJS-BODY-CAPTURE.md +2 -2
- package/docs/NEXTJS-GUIDE.md +14 -14
- package/docs/NEXTJS-QUICKSTART.md +1 -1
- package/docs/NEXTJS-SETUP-COMPLETE.md +795 -0
- package/docs/NEXTJS-WRAPPER-APPROACH.md +1 -1
- package/docs/NUXT-GUIDE.md +166 -0
- package/docs/QUICKSTART-BODY-CAPTURE.md +2 -2
- package/docs/REDACTION-EXAMPLES.md +1 -1
- package/docs/REQUEST-BODY-CAPTURE.md +19 -10
- package/docs/SOLUTION-SUMMARY.md +312 -0
- package/docs/VERCEL-OTEL-MIGRATION.md +3 -3
- package/examples/README.md +6 -6
- package/examples/instrumentation-with-auto-capture.ts +1 -1
- package/examples/nextjs-env-example.txt +2 -2
- package/examples/nextjs-instrumentation.js +1 -1
- package/examples/nextjs-instrumentation.ts +1 -1
- package/examples/nextjs-with-logging-example.md +6 -6
- package/examples/nextjs-with-options.ts +1 -1
- package/examples/test-nextjs-setup.js +1 -1
- package/firewall-cloud.js +212 -0
- package/firewall-iptables.js +139 -0
- package/firewall-only.js +38 -0
- package/firewall-tcp.js +74 -0
- package/firewall.js +720 -0
- package/free-trial-banner.js +174 -0
- package/nextjs-auto-capture.js +199 -207
- package/nextjs-middleware.js +186 -181
- package/nextjs-webpack-config.js +88 -53
- package/nextjs-wrapper.js +158 -158
- package/nextjs.d.ts +1 -1
- package/nextjs.js +639 -647
- package/nuxt-server-plugin.mjs +423 -0
- package/nuxt.d.ts +60 -0
- package/nuxt.mjs +75 -0
- package/package.json +186 -164
- package/postinstall.js +6 -6
- package/register.d.ts +1 -1
- package/register.js +39 -4
- package/resolve-ip.js +77 -0
- package/tracing.d.ts +2 -1
- package/tracing.js +295 -34
- package/web-vite.mjs +239 -156
- package/LICENSE +0 -15
package/web-vite.mjs
CHANGED
|
@@ -1,156 +1,239 @@
|
|
|
1
|
-
// web-vite.ts — Browser OTel for Vite (ESM)
|
|
2
|
-
// Defaults & naming rules match your Node tracing.js
|
|
3
|
-
|
|
4
|
-
import { WebTracerProvider, BatchSpanProcessor } from '@opentelemetry/sdk-trace-web';
|
|
5
|
-
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
|
|
6
|
-
import { Resource } from '@opentelemetry/resources';
|
|
7
|
-
import { SemanticResourceAttributes as S } from '@opentelemetry/semantic-conventions';
|
|
8
|
-
import { registerInstrumentations } from '@opentelemetry/instrumentation';
|
|
9
|
-
import { DocumentLoadInstrumentation } from '@opentelemetry/instrumentation-document-load';
|
|
10
|
-
import { UserInteractionInstrumentation } from '@opentelemetry/instrumentation-user-interaction';
|
|
11
|
-
import { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch';
|
|
12
|
-
import { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request';
|
|
13
|
-
|
|
14
|
-
// ---- helpers / env ----
|
|
15
|
-
const viteEnv: any = (import.meta as any).env || {};
|
|
16
|
-
|
|
17
|
-
function env(k: string): string | undefined {
|
|
18
|
-
// Accept both Vite envs (VITE_*) and raw names for window.__SECURENOW__
|
|
19
|
-
const direct =
|
|
20
|
-
viteEnv[k] ??
|
|
21
|
-
viteEnv[k.toUpperCase()] ??
|
|
22
|
-
viteEnv[k.toLowerCase()];
|
|
23
|
-
if (direct != null) return String(direct);
|
|
24
|
-
|
|
25
|
-
// Optionally support runtime overrides via window.__SECURENOW__
|
|
26
|
-
const w = (globalThis as any).window as any;
|
|
27
|
-
if (w && w.__SECURENOW__ && k in w.__SECURENOW__) return String(w.__SECURENOW__[k]);
|
|
28
|
-
return undefined;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function parseHeaders(str?: string) {
|
|
32
|
-
const out: Record<string, string> = {};
|
|
33
|
-
if (!str) return out;
|
|
34
|
-
String(str).split(',').forEach(raw => {
|
|
35
|
-
const s = raw.trim();
|
|
36
|
-
if (!s) return;
|
|
37
|
-
const i = s.indexOf('=');
|
|
38
|
-
if (i === -1) return;
|
|
39
|
-
out[s.slice(0, i).trim().toLowerCase()] = s.slice(i + 1).trim();
|
|
40
|
-
});
|
|
41
|
-
return out;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// ---- endpoints (same defaults as tracing.js) ----
|
|
45
|
-
const endpointBase =
|
|
46
|
-
(env('SECURENOW_INSTANCE') || env('OTEL_EXPORTER_OTLP_ENDPOINT') || 'https://freetrial.securenow.ai:4318')
|
|
47
|
-
.replace(/\/$/, '');
|
|
48
|
-
const tracesUrl =
|
|
49
|
-
env('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT') || `${endpointBase}/v1/traces`;
|
|
50
|
-
const headers = parseHeaders(env('OTEL_EXPORTER_OTLP_HEADERS'));
|
|
51
|
-
|
|
52
|
-
// ---- naming rules (mirrors tracing.js) ----
|
|
53
|
-
const rawBase = (env('OTEL_SERVICE_NAME') || env('SECURENOW_APPID') || '').trim().replace(/^['"]|['"]$/g, '');
|
|
54
|
-
const baseName = rawBase || null;
|
|
55
|
-
const noUuid = String(env('SECURENOW_NO_UUID')) === '1' || String(env('SECURENOW_NO_UUID')).toLowerCase() === 'true';
|
|
56
|
-
const strict = String(env('SECURENOW_STRICT')) === '1' || String(env('SECURENOW_STRICT')).toLowerCase() === 'true';
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
provider
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
1
|
+
// web-vite.ts — Browser OTel for Vite (ESM)
|
|
2
|
+
// Defaults & naming rules match your Node tracing.js
|
|
3
|
+
|
|
4
|
+
import { WebTracerProvider, BatchSpanProcessor } from '@opentelemetry/sdk-trace-web';
|
|
5
|
+
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
|
|
6
|
+
import { Resource } from '@opentelemetry/resources';
|
|
7
|
+
import { SemanticResourceAttributes as S } from '@opentelemetry/semantic-conventions';
|
|
8
|
+
import { registerInstrumentations } from '@opentelemetry/instrumentation';
|
|
9
|
+
import { DocumentLoadInstrumentation } from '@opentelemetry/instrumentation-document-load';
|
|
10
|
+
import { UserInteractionInstrumentation } from '@opentelemetry/instrumentation-user-interaction';
|
|
11
|
+
import { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch';
|
|
12
|
+
import { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request';
|
|
13
|
+
|
|
14
|
+
// ---- helpers / env ----
|
|
15
|
+
const viteEnv: any = (import.meta as any).env || {};
|
|
16
|
+
|
|
17
|
+
function env(k: string): string | undefined {
|
|
18
|
+
// Accept both Vite envs (VITE_*) and raw names for window.__SECURENOW__
|
|
19
|
+
const direct =
|
|
20
|
+
viteEnv[k] ??
|
|
21
|
+
viteEnv[k.toUpperCase()] ??
|
|
22
|
+
viteEnv[k.toLowerCase()];
|
|
23
|
+
if (direct != null) return String(direct);
|
|
24
|
+
|
|
25
|
+
// Optionally support runtime overrides via window.__SECURENOW__
|
|
26
|
+
const w = (globalThis as any).window as any;
|
|
27
|
+
if (w && w.__SECURENOW__ && k in w.__SECURENOW__) return String(w.__SECURENOW__[k]);
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function parseHeaders(str?: string) {
|
|
32
|
+
const out: Record<string, string> = {};
|
|
33
|
+
if (!str) return out;
|
|
34
|
+
String(str).split(',').forEach(raw => {
|
|
35
|
+
const s = raw.trim();
|
|
36
|
+
if (!s) return;
|
|
37
|
+
const i = s.indexOf('=');
|
|
38
|
+
if (i === -1) return;
|
|
39
|
+
out[s.slice(0, i).trim().toLowerCase()] = s.slice(i + 1).trim();
|
|
40
|
+
});
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// ---- endpoints (same defaults as tracing.js) ----
|
|
45
|
+
const endpointBase =
|
|
46
|
+
(env('SECURENOW_INSTANCE') || env('OTEL_EXPORTER_OTLP_ENDPOINT') || 'https://freetrial.securenow.ai:4318')
|
|
47
|
+
.replace(/\/$/, '');
|
|
48
|
+
const tracesUrl =
|
|
49
|
+
env('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT') || `${endpointBase}/v1/traces`;
|
|
50
|
+
const headers = parseHeaders(env('OTEL_EXPORTER_OTLP_HEADERS'));
|
|
51
|
+
|
|
52
|
+
// ---- naming rules (mirrors tracing.js) ----
|
|
53
|
+
const rawBase = (env('OTEL_SERVICE_NAME') || env('SECURENOW_APPID') || '').trim().replace(/^['"]|['"]$/g, '');
|
|
54
|
+
const baseName = rawBase || null;
|
|
55
|
+
const noUuid = String(env('SECURENOW_NO_UUID')) === '1' || String(env('SECURENOW_NO_UUID')).toLowerCase() === 'true';
|
|
56
|
+
const strict = String(env('SECURENOW_STRICT')) === '1' || String(env('SECURENOW_STRICT')).toLowerCase() === 'true';
|
|
57
|
+
|
|
58
|
+
function uuidv4(): string {
|
|
59
|
+
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
|
|
60
|
+
return crypto.randomUUID();
|
|
61
|
+
}
|
|
62
|
+
const bytes = new Uint8Array(16);
|
|
63
|
+
if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
|
|
64
|
+
crypto.getRandomValues(bytes);
|
|
65
|
+
} else {
|
|
66
|
+
for (let i = 0; i < 16; i++) bytes[i] = Math.floor(Math.random() * 256);
|
|
67
|
+
}
|
|
68
|
+
bytes[6] = (bytes[6] & 0x0f) | 0x40;
|
|
69
|
+
bytes[8] = (bytes[8] & 0x3f) | 0x80;
|
|
70
|
+
const hex = Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');
|
|
71
|
+
return `${hex.slice(0,8)}-${hex.slice(8,12)}-${hex.slice(12,16)}-${hex.slice(16,20)}-${hex.slice(20)}`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
let serviceName: string;
|
|
75
|
+
let disabled = false;
|
|
76
|
+
if (baseName) {
|
|
77
|
+
serviceName = noUuid ? baseName : `${baseName}-${uuidv4()}`;
|
|
78
|
+
} else {
|
|
79
|
+
if (strict) {
|
|
80
|
+
console.error('[securenow/web-vite] FATAL: SECURENOW_APPID/OTEL_SERVICE_NAME missing and SECURENOW_STRICT=1. Tracing disabled.');
|
|
81
|
+
// @ts-expect-error
|
|
82
|
+
window.__SECURENOW_DISABLED__ = true;
|
|
83
|
+
disabled = true;
|
|
84
|
+
serviceName = 'disabled';
|
|
85
|
+
} else {
|
|
86
|
+
serviceName = `securenow-free-${uuidv4()}`;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const instancePrefix = baseName || 'securenow';
|
|
91
|
+
const serviceInstanceId = `${instancePrefix}-${uuidv4()}`;
|
|
92
|
+
|
|
93
|
+
// Loud line
|
|
94
|
+
try {
|
|
95
|
+
// eslint-disable-next-line no-console
|
|
96
|
+
console.log(
|
|
97
|
+
'[securenow] web preload loaded SECURENOW_APPID=%s OTEL_SERVICE_NAME=%s SECURENOW_NO_UUID=%s SECURENOW_STRICT=%s → service.name=%s instance.id=%s',
|
|
98
|
+
JSON.stringify(env('SECURENOW_APPID')),
|
|
99
|
+
JSON.stringify(env('OTEL_SERVICE_NAME')),
|
|
100
|
+
JSON.stringify(env('SECURENOW_NO_UUID')),
|
|
101
|
+
JSON.stringify(env('SECURENOW_STRICT')),
|
|
102
|
+
serviceName,
|
|
103
|
+
serviceInstanceId
|
|
104
|
+
);
|
|
105
|
+
} catch {}
|
|
106
|
+
|
|
107
|
+
// ---- Provider / Exporter ----
|
|
108
|
+
let started = false;
|
|
109
|
+
|
|
110
|
+
export function startSecurenowWeb() {
|
|
111
|
+
if (started || disabled) return;
|
|
112
|
+
started = true;
|
|
113
|
+
|
|
114
|
+
const exporter = new OTLPTraceExporter({
|
|
115
|
+
url: tracesUrl,
|
|
116
|
+
headers,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const provider = new WebTracerProvider({
|
|
120
|
+
resource: new Resource({
|
|
121
|
+
[S.SERVICE_NAME]: serviceName,
|
|
122
|
+
[S.SERVICE_INSTANCE_ID]: serviceInstanceId,
|
|
123
|
+
[S.DEPLOYMENT_ENVIRONMENT]: viteEnv.MODE || 'production',
|
|
124
|
+
[S.SERVICE_VERSION]: viteEnv.VITE_APP_VERSION || undefined,
|
|
125
|
+
}),
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
provider.addSpanProcessor(new BatchSpanProcessor(exporter));
|
|
129
|
+
provider.register();
|
|
130
|
+
|
|
131
|
+
registerInstrumentations({
|
|
132
|
+
instrumentations: [
|
|
133
|
+
new DocumentLoadInstrumentation(),
|
|
134
|
+
new UserInteractionInstrumentation(),
|
|
135
|
+
new FetchInstrumentation({
|
|
136
|
+
propagateTraceHeaderCorsUrls: [new RegExp(`^${location.origin.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}`)],
|
|
137
|
+
ignoreUrls: [/\/vite\/hmr/, /^chrome-extension:\/\//, /sockjs/],
|
|
138
|
+
}),
|
|
139
|
+
new XMLHttpRequestInstrumentation({
|
|
140
|
+
propagateTraceHeaderCorsUrls: [new RegExp(`^${location.origin.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}`)],
|
|
141
|
+
}),
|
|
142
|
+
],
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// Optional smoke span (same flag name)
|
|
146
|
+
if (String(env('SECURENOW_TEST_SPAN')) === '1') {
|
|
147
|
+
import('@opentelemetry/api').then(api => {
|
|
148
|
+
const tracer = api.trace.getTracer('securenow-smoke');
|
|
149
|
+
const span = tracer.startSpan('securenow.startup.smoke.web'); span.end();
|
|
150
|
+
}).catch(() => {});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// eslint-disable-next-line no-console
|
|
154
|
+
console.log('[securenow] Web OTel started → %s', tracesUrl);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// ---- Free trial banner (browser DOM injection) ----
|
|
158
|
+
function injectFreeTrialBanner(): void {
|
|
159
|
+
const FREETRIAL_HOST = 'freetrial.securenow.ai';
|
|
160
|
+
const hideBanner = String(env('SECURENOW_HIDE_BANNER')) === '1';
|
|
161
|
+
if (hideBanner || !endpointBase.includes(FREETRIAL_HOST)) return;
|
|
162
|
+
if (typeof document === 'undefined') return;
|
|
163
|
+
|
|
164
|
+
function create(): void {
|
|
165
|
+
if (document.getElementById('sn-ft-banner')) return;
|
|
166
|
+
|
|
167
|
+
const d = document.createElement('div');
|
|
168
|
+
d.id = 'sn-ft-banner';
|
|
169
|
+
d.style.cssText =
|
|
170
|
+
'position:fixed;top:0;left:0;right:0;z-index:2147483647;' +
|
|
171
|
+
'background:#FEF3CD;color:#856404;padding:10px 16px;' +
|
|
172
|
+
'font-family:system-ui,-apple-system,sans-serif;font-size:13px;' +
|
|
173
|
+
'text-align:center;border-bottom:2px solid #FFE69C;' +
|
|
174
|
+
'display:flex;align-items:center;justify-content:center;gap:6px;' +
|
|
175
|
+
'box-shadow:0 2px 8px rgba(0,0,0,0.12)';
|
|
176
|
+
|
|
177
|
+
const icon = document.createElement('span');
|
|
178
|
+
icon.textContent = '\u26a0\ufe0f';
|
|
179
|
+
d.appendChild(icon);
|
|
180
|
+
|
|
181
|
+
const msg = document.createElement('span');
|
|
182
|
+
const strong = document.createElement('strong');
|
|
183
|
+
strong.textContent = 'Testing Environment:';
|
|
184
|
+
msg.appendChild(strong);
|
|
185
|
+
msg.appendChild(document.createTextNode(
|
|
186
|
+
' Only add test applications. For production usage, '
|
|
187
|
+
));
|
|
188
|
+
|
|
189
|
+
const link = document.createElement('a');
|
|
190
|
+
link.href = 'https://app.securenow.ai/dashboard/settings/instances';
|
|
191
|
+
link.target = '_blank';
|
|
192
|
+
link.rel = 'noopener';
|
|
193
|
+
link.style.cssText = 'color:#664D03;font-weight:600;text-decoration:underline';
|
|
194
|
+
link.textContent = 'create a new production instance';
|
|
195
|
+
msg.appendChild(link);
|
|
196
|
+
msg.appendChild(document.createTextNode('.'));
|
|
197
|
+
d.appendChild(msg);
|
|
198
|
+
|
|
199
|
+
const upgradeBtn = document.createElement('a');
|
|
200
|
+
upgradeBtn.href = 'https://app.securenow.ai/dashboard/settings/instances';
|
|
201
|
+
upgradeBtn.target = '_blank';
|
|
202
|
+
upgradeBtn.rel = 'noopener';
|
|
203
|
+
upgradeBtn.textContent = '\u26a1 Upgrade';
|
|
204
|
+
upgradeBtn.style.cssText =
|
|
205
|
+
'display:inline-flex;align-items:center;gap:4px;' +
|
|
206
|
+
'background:#D97706;color:#fff;padding:4px 12px;border-radius:4px;' +
|
|
207
|
+
'font-size:12px;font-weight:600;text-decoration:none;margin-left:10px;' +
|
|
208
|
+
'white-space:nowrap;transition:background 0.15s';
|
|
209
|
+
upgradeBtn.onmouseover = () => { upgradeBtn.style.background = '#B45309'; };
|
|
210
|
+
upgradeBtn.onmouseout = () => { upgradeBtn.style.background = '#D97706'; };
|
|
211
|
+
d.appendChild(upgradeBtn);
|
|
212
|
+
|
|
213
|
+
const close = document.createElement('button');
|
|
214
|
+
close.textContent = '\u00d7';
|
|
215
|
+
close.style.cssText =
|
|
216
|
+
'background:none;border:none;color:#856404;font-size:18px;' +
|
|
217
|
+
'cursor:pointer;margin-left:12px;padding:0 4px;line-height:1';
|
|
218
|
+
close.onclick = () => { d.style.display = 'none'; };
|
|
219
|
+
d.appendChild(close);
|
|
220
|
+
|
|
221
|
+
document.body.prepend(d);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (document.readyState === 'loading') {
|
|
225
|
+
document.addEventListener('DOMContentLoaded', create);
|
|
226
|
+
} else {
|
|
227
|
+
create();
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Auto-start
|
|
232
|
+
try {
|
|
233
|
+
startSecurenowWeb();
|
|
234
|
+
injectFreeTrialBanner();
|
|
235
|
+
} catch (e: any) {
|
|
236
|
+
console.error('[securenow/web-vite] failed to start:', e);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export default startSecurenowWeb;
|
package/LICENSE
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
ISC License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 SecureNow
|
|
4
|
-
|
|
5
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
-
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
-
copyright notice and this permission notice appear in all copies.
|
|
8
|
-
|
|
9
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
-
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
-
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
-
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
-
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
-
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
-
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|