featurely-site-manager 1.1.22 → 1.1.24
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/dist/cli.d.ts +1 -0
- package/dist/cli.js +80 -0
- package/dist/index.js +33 -2
- package/package.json +6 -3
- package/dist/index.d.mts +0 -224
- package/dist/index.mjs +0 -2164
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
// src/cli.ts
|
|
5
|
+
var import_fs = require("fs");
|
|
6
|
+
var import_path = require("path");
|
|
7
|
+
function parseArgs(argv) {
|
|
8
|
+
const args = {};
|
|
9
|
+
for (let i = 0; i < argv.length; i++) {
|
|
10
|
+
if (argv[i].startsWith("--") && i + 1 < argv.length && !argv[i + 1].startsWith("--")) {
|
|
11
|
+
args[argv[i].slice(2)] = argv[i + 1];
|
|
12
|
+
i++;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return args;
|
|
16
|
+
}
|
|
17
|
+
async function main() {
|
|
18
|
+
var _a, _b, _c;
|
|
19
|
+
const rawArgs = process.argv.slice(2);
|
|
20
|
+
const isScanPackages = rawArgs[0] === "scan" && rawArgs[1] === "packages";
|
|
21
|
+
if (!isScanPackages) {
|
|
22
|
+
console.error("Usage: featurely-site-manager scan packages --key <api-key> --project <project-id>");
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
const args = parseArgs(rawArgs.slice(2));
|
|
26
|
+
const apiKey = args["key"];
|
|
27
|
+
const projectId = args["project"];
|
|
28
|
+
const baseUrl = (_a = args["url"]) != null ? _a : "https://featurely.no";
|
|
29
|
+
if (!apiKey) {
|
|
30
|
+
console.error("Error: --key is required");
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
if (!projectId) {
|
|
34
|
+
console.error("Error: --project is required");
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
const pkgPath = (0, import_path.resolve)(process.cwd(), "package.json");
|
|
38
|
+
let pkgJson;
|
|
39
|
+
try {
|
|
40
|
+
pkgJson = JSON.parse((0, import_fs.readFileSync)(pkgPath, "utf8"));
|
|
41
|
+
} catch {
|
|
42
|
+
console.error(`Error: Could not read package.json at ${pkgPath}`);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
const deps = (_b = pkgJson.dependencies) != null ? _b : {};
|
|
46
|
+
const devDeps = (_c = pkgJson.devDependencies) != null ? _c : {};
|
|
47
|
+
const packages = [
|
|
48
|
+
...Object.entries(deps).map(([name, version]) => ({ name, version: version.replace(/^[\^~>=<]/, "") })),
|
|
49
|
+
...Object.entries(devDeps).map(([name, version]) => ({ name, version: version.replace(/^[\^~>=<]/, "") }))
|
|
50
|
+
];
|
|
51
|
+
if (packages.length === 0) {
|
|
52
|
+
console.log("No dependencies found in package.json \u2014 nothing to scan.");
|
|
53
|
+
process.exit(0);
|
|
54
|
+
}
|
|
55
|
+
console.log(`Scanning ${packages.length} packages for project ${projectId}\u2026`);
|
|
56
|
+
const url = `${baseUrl}/api/projects/${projectId}/packages`;
|
|
57
|
+
let res;
|
|
58
|
+
try {
|
|
59
|
+
res = await fetch(url, {
|
|
60
|
+
method: "POST",
|
|
61
|
+
headers: {
|
|
62
|
+
"Content-Type": "application/json",
|
|
63
|
+
"x-api-key": apiKey
|
|
64
|
+
},
|
|
65
|
+
body: JSON.stringify({ packages })
|
|
66
|
+
});
|
|
67
|
+
} catch (err) {
|
|
68
|
+
console.error("Error: Network request failed.", err);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
if (!res.ok) {
|
|
72
|
+
const body = await res.text();
|
|
73
|
+
console.error(`Error: API returned ${res.status}. ${body}`);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
const data = await res.json();
|
|
77
|
+
const count = Array.isArray(data.packages) ? data.packages.length : packages.length;
|
|
78
|
+
console.log(`\u2713 Scan complete. ${count} packages analysed. View results in your Featurely dashboard.`);
|
|
79
|
+
}
|
|
80
|
+
main();
|
package/dist/index.js
CHANGED
|
@@ -1089,18 +1089,49 @@ var _SiteManager = class _SiteManager {
|
|
|
1089
1089
|
setupWebVitals() {
|
|
1090
1090
|
if (typeof PerformanceObserver === "undefined") return;
|
|
1091
1091
|
try {
|
|
1092
|
+
let lcpValue = 0;
|
|
1093
|
+
let lcpReported = false;
|
|
1092
1094
|
const lcpObs = new PerformanceObserver((list) => {
|
|
1093
1095
|
const entries = list.getEntries();
|
|
1094
1096
|
const last = entries[entries.length - 1];
|
|
1095
1097
|
if (last) {
|
|
1098
|
+
lcpValue = Math.round(last.startTime);
|
|
1099
|
+
}
|
|
1100
|
+
});
|
|
1101
|
+
lcpObs.observe({ type: "largest-contentful-paint", buffered: true });
|
|
1102
|
+
const reportLcp = () => {
|
|
1103
|
+
if (lcpValue > 0 && !lcpReported) {
|
|
1104
|
+
lcpReported = true;
|
|
1096
1105
|
this.trackEvent("web_vital", {
|
|
1097
1106
|
metric: "LCP",
|
|
1098
|
-
valueMs:
|
|
1107
|
+
valueMs: lcpValue,
|
|
1099
1108
|
path: window.location.pathname
|
|
1100
1109
|
});
|
|
1101
1110
|
}
|
|
1111
|
+
};
|
|
1112
|
+
const interactionTypes = [
|
|
1113
|
+
"click",
|
|
1114
|
+
"keydown",
|
|
1115
|
+
"scroll",
|
|
1116
|
+
"pointerdown",
|
|
1117
|
+
"touchstart"
|
|
1118
|
+
];
|
|
1119
|
+
const onFirstInteraction = () => {
|
|
1120
|
+
reportLcp();
|
|
1121
|
+
interactionTypes.forEach(
|
|
1122
|
+
(t) => window.removeEventListener(t, onFirstInteraction)
|
|
1123
|
+
);
|
|
1124
|
+
};
|
|
1125
|
+
interactionTypes.forEach(
|
|
1126
|
+
(t) => window.addEventListener(t, onFirstInteraction, {
|
|
1127
|
+
once: true,
|
|
1128
|
+
passive: true
|
|
1129
|
+
})
|
|
1130
|
+
);
|
|
1131
|
+
window.addEventListener("visibilitychange", () => {
|
|
1132
|
+
if (document.visibilityState === "hidden") reportLcp();
|
|
1102
1133
|
});
|
|
1103
|
-
|
|
1134
|
+
window.addEventListener("pagehide", reportLcp);
|
|
1104
1135
|
} catch {
|
|
1105
1136
|
}
|
|
1106
1137
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "featurely-site-manager",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.24",
|
|
4
4
|
"description": "Complete site management SDK for maintenance mode, status messages, feature flags, version checking, and analytics",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
"require": "./dist/index.js"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
|
+
"bin": {
|
|
16
|
+
"featurely-site-manager": "./dist/cli.js"
|
|
17
|
+
},
|
|
15
18
|
"files": [
|
|
16
19
|
"dist",
|
|
17
20
|
"README.md",
|
|
@@ -19,8 +22,8 @@
|
|
|
19
22
|
"CHANGELOG.md"
|
|
20
23
|
],
|
|
21
24
|
"scripts": {
|
|
22
|
-
"build": "tsup src/index.ts --format cjs
|
|
23
|
-
"dev": "tsup src/index.ts --format cjs
|
|
25
|
+
"build": "tsup src/index.ts src/cli.ts --format cjs --dts --clean",
|
|
26
|
+
"dev": "tsup src/index.ts src/cli.ts --format cjs --dts --watch",
|
|
24
27
|
"prepublishOnly": "npm run build"
|
|
25
28
|
},
|
|
26
29
|
"keywords": [
|
package/dist/index.d.mts
DELETED
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
type MessageType = "info" | "warning" | "error" | "success";
|
|
2
|
-
type MessagePosition = "top" | "bottom";
|
|
3
|
-
type MessageStyle = "banner" | "toast";
|
|
4
|
-
interface StatusMessage {
|
|
5
|
-
id: string;
|
|
6
|
-
type: MessageType;
|
|
7
|
-
title: string;
|
|
8
|
-
message: string;
|
|
9
|
-
icon?: string;
|
|
10
|
-
dismissible: boolean;
|
|
11
|
-
position: MessagePosition;
|
|
12
|
-
style: MessageStyle;
|
|
13
|
-
expiresAt?: string;
|
|
14
|
-
startsAt?: string;
|
|
15
|
-
targetPages?: string[];
|
|
16
|
-
cta?: {
|
|
17
|
-
text: string;
|
|
18
|
-
url: string;
|
|
19
|
-
action?: string;
|
|
20
|
-
};
|
|
21
|
-
priority?: number;
|
|
22
|
-
}
|
|
23
|
-
interface FeatureFlag {
|
|
24
|
-
id: string;
|
|
25
|
-
key: string;
|
|
26
|
-
name: string;
|
|
27
|
-
description?: string;
|
|
28
|
-
enabled: boolean;
|
|
29
|
-
rolloutPercentage?: number;
|
|
30
|
-
targetEmails?: string[];
|
|
31
|
-
excludeEmails?: string[];
|
|
32
|
-
variants?: {
|
|
33
|
-
key: string;
|
|
34
|
-
name: string;
|
|
35
|
-
weight: number;
|
|
36
|
-
}[];
|
|
37
|
-
defaultVariant?: string;
|
|
38
|
-
targetAttributes?: Array<{
|
|
39
|
-
attribute: string;
|
|
40
|
-
operator: "equals" | "not_equals" | "contains" | "greater_than" | "less_than";
|
|
41
|
-
value: string | number | boolean;
|
|
42
|
-
}>;
|
|
43
|
-
}
|
|
44
|
-
interface MaintenanceConfig {
|
|
45
|
-
enabled: boolean;
|
|
46
|
-
type: "default" | "custom";
|
|
47
|
-
customHtml?: string;
|
|
48
|
-
expectedRestoration?: string;
|
|
49
|
-
showStatusLink: boolean;
|
|
50
|
-
statusPageUrl?: string;
|
|
51
|
-
whitelist: {
|
|
52
|
-
localStorageKeys?: string[];
|
|
53
|
-
emails?: string[];
|
|
54
|
-
ips?: string[];
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
interface AppVersion {
|
|
58
|
-
version: string;
|
|
59
|
-
title: string;
|
|
60
|
-
releaseNotes?: string;
|
|
61
|
-
downloadUrl?: string;
|
|
62
|
-
platformUrls?: Record<string, string>;
|
|
63
|
-
releaseDate: string;
|
|
64
|
-
isBeta?: boolean;
|
|
65
|
-
rolloutPercentage?: number;
|
|
66
|
-
}
|
|
67
|
-
interface VersionCheckResponse {
|
|
68
|
-
updateAvailable: boolean;
|
|
69
|
-
updateRequired: boolean;
|
|
70
|
-
updateRecommended: boolean;
|
|
71
|
-
updateType?: "major" | "minor" | "patch" | "hash" | "unknown";
|
|
72
|
-
latestVersion?: AppVersion;
|
|
73
|
-
}
|
|
74
|
-
interface VersionUpdateRules {
|
|
75
|
-
major?: "required" | "available";
|
|
76
|
-
minor?: "required" | "available";
|
|
77
|
-
patch?: "required" | "recommended" | "available";
|
|
78
|
-
}
|
|
79
|
-
interface SiteConfig {
|
|
80
|
-
maintenance: MaintenanceConfig;
|
|
81
|
-
messages: StatusMessage[];
|
|
82
|
-
featureFlags: FeatureFlag[];
|
|
83
|
-
lastUpdated: string;
|
|
84
|
-
}
|
|
85
|
-
interface SiteManagerConfig {
|
|
86
|
-
apiKey: string;
|
|
87
|
-
projectId: string;
|
|
88
|
-
apiUrl?: string;
|
|
89
|
-
environment?: string;
|
|
90
|
-
pollInterval?: number;
|
|
91
|
-
userEmail?: string;
|
|
92
|
-
bypassCheck?: () => boolean;
|
|
93
|
-
onMaintenanceEnabled?: (config: MaintenanceConfig) => void;
|
|
94
|
-
onMaintenanceDisabled?: () => void;
|
|
95
|
-
onMessageReceived?: (message: StatusMessage) => void;
|
|
96
|
-
onMessageDismissed?: (messageId: string) => void;
|
|
97
|
-
onFeatureFlagsUpdated?: (flags: FeatureFlag[]) => void;
|
|
98
|
-
userId?: string;
|
|
99
|
-
customAttributes?: Record<string, string | number | boolean>;
|
|
100
|
-
bootstrapFlags?: Record<string, boolean>;
|
|
101
|
-
enableAnalytics?: boolean;
|
|
102
|
-
analyticsFlushInterval?: number;
|
|
103
|
-
appVersion?: string;
|
|
104
|
-
enableVersionCheck?: boolean;
|
|
105
|
-
versionCheckInterval?: number;
|
|
106
|
-
onUpdateAvailable?: (versionInfo: VersionCheckResponse) => void;
|
|
107
|
-
onUpdateRequired?: (versionInfo: VersionCheckResponse) => void;
|
|
108
|
-
platform?: string;
|
|
109
|
-
updateRules?: VersionUpdateRules;
|
|
110
|
-
onError?: (error: Error) => void;
|
|
111
|
-
debugMode?: boolean;
|
|
112
|
-
debugSecret?: string;
|
|
113
|
-
autoInjectBanners?: boolean;
|
|
114
|
-
autoCaptureClicks?: boolean;
|
|
115
|
-
}
|
|
116
|
-
declare class SiteManager {
|
|
117
|
-
private config;
|
|
118
|
-
private siteConfig;
|
|
119
|
-
private configETag;
|
|
120
|
-
private pollIntervalId;
|
|
121
|
-
private versionCheckIntervalId;
|
|
122
|
-
private messageContainers;
|
|
123
|
-
private dismissedMessages;
|
|
124
|
-
private featureFlagBuckets;
|
|
125
|
-
private analyticsQueue;
|
|
126
|
-
private analyticsFlushIntervalId;
|
|
127
|
-
private sessionId;
|
|
128
|
-
private consecutiveFetchFailures;
|
|
129
|
-
private pageTrackingSetup;
|
|
130
|
-
private currentPagePath;
|
|
131
|
-
private currentPageSearch;
|
|
132
|
-
private pageEntryTime;
|
|
133
|
-
private static readonly MAX_CONSECUTIVE_FAILURES;
|
|
134
|
-
private lastVersionCheck;
|
|
135
|
-
private debugOverlayEl;
|
|
136
|
-
private debugRefreshId;
|
|
137
|
-
private debugLogs;
|
|
138
|
-
private networkLog;
|
|
139
|
-
private analyticsEventsSent;
|
|
140
|
-
private debugMinimized;
|
|
141
|
-
private debugTab;
|
|
142
|
-
private recentAnalyticsEvents;
|
|
143
|
-
private testFlagKey;
|
|
144
|
-
private testFeedback;
|
|
145
|
-
private errorCount;
|
|
146
|
-
private consoleIntercepted;
|
|
147
|
-
private visitorId;
|
|
148
|
-
private flagOverrides;
|
|
149
|
-
private originalConsoleError;
|
|
150
|
-
private originalConsoleWarn;
|
|
151
|
-
constructor(config: SiteManagerConfig);
|
|
152
|
-
init(): Promise<void>;
|
|
153
|
-
destroy(): void;
|
|
154
|
-
setUser(email: string, userId?: string, customAttributes?: Record<string, string | number | boolean>): void;
|
|
155
|
-
isFeatureEnabled(flagKey: string, defaultValue?: boolean): boolean;
|
|
156
|
-
getFeatureVariant(flagKey: string): string | null;
|
|
157
|
-
getAllFeatureFlags(): FeatureFlag[];
|
|
158
|
-
getEnabledFeatures(): string[];
|
|
159
|
-
getActiveEnvironment(): {
|
|
160
|
-
id: string;
|
|
161
|
-
name: string;
|
|
162
|
-
slug: string;
|
|
163
|
-
} | null;
|
|
164
|
-
isErrorLoggingEnabled(): boolean;
|
|
165
|
-
overrideFlag(flagKey: string, value: boolean | null): void;
|
|
166
|
-
isInMaintenanceMode(): boolean;
|
|
167
|
-
getActiveMessages(): StatusMessage[];
|
|
168
|
-
refresh(): Promise<void>;
|
|
169
|
-
trackEvent(eventName: string, properties?: Record<string, string | number | boolean>): void;
|
|
170
|
-
track404(path?: string): void;
|
|
171
|
-
private fetchConfig;
|
|
172
|
-
private startPolling;
|
|
173
|
-
private stopPolling;
|
|
174
|
-
private startAnalyticsFlushing;
|
|
175
|
-
private stopAnalyticsFlushing;
|
|
176
|
-
private flushAnalytics;
|
|
177
|
-
private debugLog;
|
|
178
|
-
private debugNetwork;
|
|
179
|
-
private stopDebugOverlay;
|
|
180
|
-
private setupGlobalErrorCapture;
|
|
181
|
-
private setupDebugOverlay;
|
|
182
|
-
private renderDebugOverlay;
|
|
183
|
-
private handleTestAction;
|
|
184
|
-
private parseUtmParams;
|
|
185
|
-
private setupWebVitals;
|
|
186
|
-
private setupOutboundLinkTracking;
|
|
187
|
-
private setupAutoClickCapture;
|
|
188
|
-
private setupPageTracking;
|
|
189
|
-
private trackPageView;
|
|
190
|
-
private trackPageExit;
|
|
191
|
-
private onNavigate;
|
|
192
|
-
private generateSessionId;
|
|
193
|
-
checkVersion(currentVersion?: string): Promise<VersionCheckResponse | null>;
|
|
194
|
-
forceUpdateWeb(): Promise<void>;
|
|
195
|
-
getLastVersionCheck(): VersionCheckResponse | null;
|
|
196
|
-
private startVersionChecking;
|
|
197
|
-
private stopVersionChecking;
|
|
198
|
-
private resolveEnvironment;
|
|
199
|
-
private hostnameMatchesEnv;
|
|
200
|
-
private matchHostnamePattern;
|
|
201
|
-
private evaluateFeatureFlag;
|
|
202
|
-
private getUserBucket;
|
|
203
|
-
private simpleHash;
|
|
204
|
-
private getAnonymousId;
|
|
205
|
-
private getOrCreateVisitorId;
|
|
206
|
-
private checkMaintenanceMode;
|
|
207
|
-
private enableMaintenanceMode;
|
|
208
|
-
private disableMaintenanceMode;
|
|
209
|
-
private shouldBypassMaintenance;
|
|
210
|
-
private showMaintenancePage;
|
|
211
|
-
private hideMaintenancePage;
|
|
212
|
-
private getDefaultMaintenanceHtml;
|
|
213
|
-
private updateMessages;
|
|
214
|
-
private showMessage;
|
|
215
|
-
private dismissMessage;
|
|
216
|
-
private clearMessages;
|
|
217
|
-
private handleMessageAction;
|
|
218
|
-
private getDefaultIcon;
|
|
219
|
-
private loadDismissedMessages;
|
|
220
|
-
private saveDismissedMessages;
|
|
221
|
-
private injectStyles;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
export { type AppVersion, type FeatureFlag, type MaintenanceConfig, type MessagePosition, type MessageStyle, type MessageType, type SiteConfig, SiteManager, type SiteManagerConfig, type StatusMessage, type VersionCheckResponse, type VersionUpdateRules, SiteManager as default };
|