@budibase/backend-core 2.32.12 → 2.32.13
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/index.js +125 -49
- package/dist/index.js.map +4 -4
- package/dist/index.js.meta.json +1 -1
- package/dist/package.json +4 -4
- package/dist/plugins.js.meta.json +1 -1
- package/dist/src/db/couch/DatabaseImpl.js +10 -2
- package/dist/src/db/couch/DatabaseImpl.js.map +1 -1
- package/dist/src/features/features.d.ts +47 -0
- package/dist/src/features/features.js +269 -0
- package/dist/src/features/features.js.map +1 -0
- package/dist/src/features/index.d.ts +2 -39
- package/dist/src/features/index.js +6 -235
- package/dist/src/features/index.js.map +1 -1
- package/dist/src/features/tests/utils.d.ts +3 -0
- package/dist/src/features/tests/utils.js +56 -0
- package/dist/src/features/tests/utils.js.map +1 -0
- package/dist/src/middleware/passport/sso/sso.js +0 -25
- package/dist/src/middleware/passport/sso/sso.js.map +1 -1
- package/dist/src/users/users.js +8 -1
- package/dist/src/users/users.js.map +1 -1
- package/dist/tests/core/utilities/structures/accounts.js +2 -2
- package/dist/tests/core/utilities/structures/accounts.js.map +1 -1
- package/dist/tests/core/utilities/structures/users.js +2 -5
- package/dist/tests/core/utilities/structures/users.js.map +1 -1
- package/package.json +4 -4
- package/src/db/couch/DatabaseImpl.ts +12 -2
- package/src/features/features.ts +300 -0
- package/src/features/index.ts +2 -281
- package/src/features/tests/utils.ts +64 -0
- package/src/middleware/passport/sso/sso.ts +0 -24
- package/src/users/users.ts +10 -2
- package/tests/core/utilities/structures/accounts.ts +0 -4
- package/tests/core/utilities/structures/users.ts +0 -5
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
35
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
|
+
};
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
exports.flags = exports.FlagSet = exports.Flag = void 0;
|
|
39
|
+
exports.init = init;
|
|
40
|
+
exports.shutdown = shutdown;
|
|
41
|
+
exports.parseEnvFlags = parseEnvFlags;
|
|
42
|
+
const environment_1 = __importDefault(require("../environment"));
|
|
43
|
+
const context = __importStar(require("../context"));
|
|
44
|
+
const posthog_node_1 = require("posthog-node");
|
|
45
|
+
const types_1 = require("@budibase/types");
|
|
46
|
+
const dd_trace_1 = __importDefault(require("dd-trace"));
|
|
47
|
+
const utils_1 = require("../utils");
|
|
48
|
+
let posthog;
|
|
49
|
+
function init(opts) {
|
|
50
|
+
if (environment_1.default.POSTHOG_TOKEN &&
|
|
51
|
+
environment_1.default.POSTHOG_API_HOST &&
|
|
52
|
+
!environment_1.default.SELF_HOSTED &&
|
|
53
|
+
environment_1.default.POSTHOG_FEATURE_FLAGS_ENABLED) {
|
|
54
|
+
console.log("initializing posthog client...");
|
|
55
|
+
posthog = new posthog_node_1.PostHog(environment_1.default.POSTHOG_TOKEN, Object.assign({ host: environment_1.default.POSTHOG_API_HOST, personalApiKey: environment_1.default.POSTHOG_PERSONAL_TOKEN, featureFlagsPollingInterval: utils_1.Duration.fromMinutes(3).toMs() }, opts));
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
console.log("posthog disabled");
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function shutdown() {
|
|
62
|
+
posthog === null || posthog === void 0 ? void 0 : posthog.shutdown();
|
|
63
|
+
}
|
|
64
|
+
class Flag {
|
|
65
|
+
static boolean(defaultValue) {
|
|
66
|
+
return new BooleanFlag(defaultValue);
|
|
67
|
+
}
|
|
68
|
+
static string(defaultValue) {
|
|
69
|
+
return new StringFlag(defaultValue);
|
|
70
|
+
}
|
|
71
|
+
static number(defaultValue) {
|
|
72
|
+
return new NumberFlag(defaultValue);
|
|
73
|
+
}
|
|
74
|
+
constructor(defaultValue) {
|
|
75
|
+
this.defaultValue = defaultValue;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
exports.Flag = Flag;
|
|
79
|
+
class BooleanFlag extends Flag {
|
|
80
|
+
parse(value) {
|
|
81
|
+
if (typeof value === "string") {
|
|
82
|
+
return ["true", "t", "1"].includes(value.toLowerCase());
|
|
83
|
+
}
|
|
84
|
+
if (typeof value === "boolean") {
|
|
85
|
+
return value;
|
|
86
|
+
}
|
|
87
|
+
throw new Error(`could not parse value "${value}" as boolean`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
class StringFlag extends Flag {
|
|
91
|
+
parse(value) {
|
|
92
|
+
if (typeof value === "string") {
|
|
93
|
+
return value;
|
|
94
|
+
}
|
|
95
|
+
throw new Error(`could not parse value "${value}" as string`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
class NumberFlag extends Flag {
|
|
99
|
+
parse(value) {
|
|
100
|
+
if (typeof value === "number") {
|
|
101
|
+
return value;
|
|
102
|
+
}
|
|
103
|
+
if (typeof value === "string") {
|
|
104
|
+
const parsed = parseFloat(value);
|
|
105
|
+
if (!isNaN(parsed)) {
|
|
106
|
+
return parsed;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
throw new Error(`could not parse value "${value}" as number`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function parseEnvFlags(flags) {
|
|
113
|
+
const split = flags.split(",").map(x => x.split(":"));
|
|
114
|
+
const result = [];
|
|
115
|
+
for (const [tenantId, ...features] of split) {
|
|
116
|
+
for (let feature of features) {
|
|
117
|
+
let value = true;
|
|
118
|
+
if (feature.startsWith("!")) {
|
|
119
|
+
feature = feature.slice(1);
|
|
120
|
+
value = false;
|
|
121
|
+
}
|
|
122
|
+
result.push({ tenantId, key: feature, value });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
class FlagSet {
|
|
128
|
+
constructor(flagSchema) {
|
|
129
|
+
this.flagSchema = flagSchema;
|
|
130
|
+
this.setId = crypto.randomUUID();
|
|
131
|
+
}
|
|
132
|
+
defaults() {
|
|
133
|
+
return Object.keys(this.flagSchema).reduce((acc, key) => {
|
|
134
|
+
const typedKey = key;
|
|
135
|
+
acc[typedKey] = this.flagSchema[key].defaultValue;
|
|
136
|
+
return acc;
|
|
137
|
+
}, {});
|
|
138
|
+
}
|
|
139
|
+
isFlagName(name) {
|
|
140
|
+
return this.flagSchema[name] !== undefined;
|
|
141
|
+
}
|
|
142
|
+
get(key, ctx) {
|
|
143
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
144
|
+
const flags = yield this.fetch(ctx);
|
|
145
|
+
return flags[key];
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
isEnabled(key, ctx) {
|
|
149
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
150
|
+
const flags = yield this.fetch(ctx);
|
|
151
|
+
return flags[key];
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
fetch(ctx) {
|
|
155
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
156
|
+
return yield dd_trace_1.default.trace("features.fetch", (span) => __awaiter(this, void 0, void 0, function* () {
|
|
157
|
+
var _a, _b;
|
|
158
|
+
const cachedFlags = context.getFeatureFlags(this.setId);
|
|
159
|
+
if (cachedFlags) {
|
|
160
|
+
span === null || span === void 0 ? void 0 : span.addTags({ fromCache: true });
|
|
161
|
+
return cachedFlags;
|
|
162
|
+
}
|
|
163
|
+
const tags = {};
|
|
164
|
+
const flagValues = this.defaults();
|
|
165
|
+
const currentTenantId = context.getTenantId();
|
|
166
|
+
const specificallySetFalse = new Set();
|
|
167
|
+
for (const { tenantId, key, value } of parseEnvFlags(environment_1.default.TENANT_FEATURE_FLAGS || "")) {
|
|
168
|
+
if (!tenantId || (tenantId !== "*" && tenantId !== currentTenantId)) {
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
tags[`readFromEnvironmentVars`] = true;
|
|
172
|
+
if (value === false) {
|
|
173
|
+
specificallySetFalse.add(key);
|
|
174
|
+
}
|
|
175
|
+
// ignore unknown flags
|
|
176
|
+
if (!this.isFlagName(key)) {
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
if (typeof flagValues[key] !== "boolean") {
|
|
180
|
+
throw new Error(`Feature: ${key} is not a boolean`);
|
|
181
|
+
}
|
|
182
|
+
// @ts-expect-error - TS does not like you writing into a generic type,
|
|
183
|
+
// but we know that it's okay in this case because it's just an object.
|
|
184
|
+
flagValues[key] = value;
|
|
185
|
+
tags[`flags.${key}.source`] = "environment";
|
|
186
|
+
}
|
|
187
|
+
const license = (_a = ctx === null || ctx === void 0 ? void 0 : ctx.user) === null || _a === void 0 ? void 0 : _a.license;
|
|
188
|
+
if (license) {
|
|
189
|
+
tags[`readFromLicense`] = true;
|
|
190
|
+
for (const feature of license.features) {
|
|
191
|
+
if (!this.isFlagName(feature)) {
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
if (flagValues[feature] === true ||
|
|
195
|
+
specificallySetFalse.has(feature)) {
|
|
196
|
+
// If the flag is already set to through environment variables, we
|
|
197
|
+
// don't want to override it back to false here.
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
// @ts-expect-error - TS does not like you writing into a generic type,
|
|
201
|
+
// but we know that it's okay in this case because it's just an object.
|
|
202
|
+
flagValues[feature] = true;
|
|
203
|
+
tags[`flags.${feature}.source`] = "license";
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
const identity = context.getIdentity();
|
|
207
|
+
tags[`identity.type`] = identity === null || identity === void 0 ? void 0 : identity.type;
|
|
208
|
+
tags[`identity.tenantId`] = identity === null || identity === void 0 ? void 0 : identity.tenantId;
|
|
209
|
+
tags[`identity._id`] = identity === null || identity === void 0 ? void 0 : identity._id;
|
|
210
|
+
if (posthog && (identity === null || identity === void 0 ? void 0 : identity.type) === types_1.IdentityType.USER) {
|
|
211
|
+
tags[`readFromPostHog`] = true;
|
|
212
|
+
const personProperties = {};
|
|
213
|
+
if (identity.tenantId) {
|
|
214
|
+
personProperties.tenantId = identity.tenantId;
|
|
215
|
+
}
|
|
216
|
+
const posthogFlags = yield posthog.getAllFlagsAndPayloads(identity._id, {
|
|
217
|
+
personProperties,
|
|
218
|
+
});
|
|
219
|
+
for (const [name, value] of Object.entries(posthogFlags.featureFlags)) {
|
|
220
|
+
if (!this.isFlagName(name)) {
|
|
221
|
+
// We don't want an unexpected PostHog flag to break the app, so we
|
|
222
|
+
// just log it and continue.
|
|
223
|
+
console.warn(`Unexpected posthog flag "${name}": ${value}`);
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
if (flagValues[name] === true || specificallySetFalse.has(name)) {
|
|
227
|
+
// If the flag is already set to through environment variables, we
|
|
228
|
+
// don't want to override it back to false here.
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
const payload = (_b = posthogFlags.featureFlagPayloads) === null || _b === void 0 ? void 0 : _b[name];
|
|
232
|
+
const flag = this.flagSchema[name];
|
|
233
|
+
try {
|
|
234
|
+
// @ts-expect-error - TS does not like you writing into a generic
|
|
235
|
+
// type, but we know that it's okay in this case because it's just
|
|
236
|
+
// an object.
|
|
237
|
+
flagValues[name] = flag.parse(payload || value);
|
|
238
|
+
tags[`flags.${name}.source`] = "posthog";
|
|
239
|
+
}
|
|
240
|
+
catch (err) {
|
|
241
|
+
// We don't want an invalid PostHog flag to break the app, so we just
|
|
242
|
+
// log it and continue.
|
|
243
|
+
console.warn(`Error parsing posthog flag "${name}": ${value}`, err);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
context.setFeatureFlags(this.setId, flagValues);
|
|
248
|
+
for (const [key, value] of Object.entries(flagValues)) {
|
|
249
|
+
tags[`flags.${key}.value`] = value;
|
|
250
|
+
}
|
|
251
|
+
span === null || span === void 0 ? void 0 : span.addTags(tags);
|
|
252
|
+
return flagValues;
|
|
253
|
+
}));
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
exports.FlagSet = FlagSet;
|
|
258
|
+
// This is the primary source of truth for feature flags. If you want to add a
|
|
259
|
+
// new flag, add it here and use the `fetch` and `get` functions to access it.
|
|
260
|
+
// All of the machinery in this file is to make sure that flags have their
|
|
261
|
+
// default values set correctly and their types flow through the system.
|
|
262
|
+
exports.flags = new FlagSet({
|
|
263
|
+
DEFAULT_VALUES: Flag.boolean(environment_1.default.isDev()),
|
|
264
|
+
AUTOMATION_BRANCHING: Flag.boolean(environment_1.default.isDev()),
|
|
265
|
+
SQS: Flag.boolean(environment_1.default.isDev()),
|
|
266
|
+
[types_1.FeatureFlag.AI_CUSTOM_CONFIGS]: Flag.boolean(environment_1.default.isDev()),
|
|
267
|
+
[types_1.FeatureFlag.ENRICHED_RELATIONSHIPS]: Flag.boolean(environment_1.default.isDev()),
|
|
268
|
+
});
|
|
269
|
+
//# sourceMappingURL=features.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"features.js","sourceRoot":"","sources":["../../../src/features/features.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,39 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export declare function init(opts?: PostHogOptions): void;
|
|
4
|
-
export declare function shutdown(): void;
|
|
5
|
-
export declare abstract class Flag<T> {
|
|
6
|
-
defaultValue: T;
|
|
7
|
-
static boolean(defaultValue: boolean): Flag<boolean>;
|
|
8
|
-
static string(defaultValue: string): Flag<string>;
|
|
9
|
-
static number(defaultValue: number): Flag<number>;
|
|
10
|
-
protected constructor(defaultValue: T);
|
|
11
|
-
abstract parse(value: any): T;
|
|
12
|
-
}
|
|
13
|
-
type UnwrapFlag<F> = F extends Flag<infer U> ? U : never;
|
|
14
|
-
export type FlagValues<T> = {
|
|
15
|
-
[K in keyof T]: UnwrapFlag<T[K]>;
|
|
16
|
-
};
|
|
17
|
-
type KeysOfType<T, U> = {
|
|
18
|
-
[K in keyof T]: T[K] extends Flag<U> ? K : never;
|
|
19
|
-
}[keyof T];
|
|
20
|
-
export declare class FlagSet<V extends Flag<any>, T extends {
|
|
21
|
-
[key: string]: V;
|
|
22
|
-
}> {
|
|
23
|
-
private readonly flagSchema;
|
|
24
|
-
private readonly setId;
|
|
25
|
-
constructor(flagSchema: T);
|
|
26
|
-
defaults(): FlagValues<T>;
|
|
27
|
-
isFlagName(name: string | number | symbol): name is keyof T;
|
|
28
|
-
get<K extends keyof T>(key: K, ctx?: UserCtx): Promise<FlagValues<T>[K]>;
|
|
29
|
-
isEnabled<K extends KeysOfType<T, boolean>>(key: K, ctx?: UserCtx): Promise<boolean>;
|
|
30
|
-
fetch(ctx?: UserCtx): Promise<FlagValues<T>>;
|
|
31
|
-
}
|
|
32
|
-
export declare const flags: FlagSet<Flag<any>, {
|
|
33
|
-
DEFAULT_VALUES: Flag<boolean>;
|
|
34
|
-
AUTOMATION_BRANCHING: Flag<boolean>;
|
|
35
|
-
SQS: Flag<boolean>;
|
|
36
|
-
AI_CUSTOM_CONFIGS: Flag<boolean>;
|
|
37
|
-
ENRICHED_RELATIONSHIPS: Flag<boolean>;
|
|
38
|
-
}>;
|
|
39
|
-
export {};
|
|
1
|
+
export * from "./features";
|
|
2
|
+
export * as testutils from "./tests/utils";
|
|
@@ -15,6 +15,9 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
19
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
20
|
+
};
|
|
18
21
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
22
|
if (mod && mod.__esModule) return mod;
|
|
20
23
|
var result = {};
|
|
@@ -22,240 +25,8 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
25
|
__setModuleDefault(result, mod);
|
|
23
26
|
return result;
|
|
24
27
|
};
|
|
25
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
-
});
|
|
33
|
-
};
|
|
34
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
35
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
|
-
};
|
|
37
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
-
exports.
|
|
39
|
-
exports
|
|
40
|
-
exports.
|
|
41
|
-
const environment_1 = __importDefault(require("../environment"));
|
|
42
|
-
const context = __importStar(require("../context"));
|
|
43
|
-
const posthog_node_1 = require("posthog-node");
|
|
44
|
-
const types_1 = require("@budibase/types");
|
|
45
|
-
const dd_trace_1 = __importDefault(require("dd-trace"));
|
|
46
|
-
const utils_1 = require("../utils");
|
|
47
|
-
let posthog;
|
|
48
|
-
function init(opts) {
|
|
49
|
-
if (environment_1.default.POSTHOG_TOKEN &&
|
|
50
|
-
environment_1.default.POSTHOG_API_HOST &&
|
|
51
|
-
!environment_1.default.SELF_HOSTED &&
|
|
52
|
-
environment_1.default.POSTHOG_FEATURE_FLAGS_ENABLED) {
|
|
53
|
-
console.log("initializing posthog client...");
|
|
54
|
-
posthog = new posthog_node_1.PostHog(environment_1.default.POSTHOG_TOKEN, Object.assign({ host: environment_1.default.POSTHOG_API_HOST, personalApiKey: environment_1.default.POSTHOG_PERSONAL_TOKEN, featureFlagsPollingInterval: utils_1.Duration.fromMinutes(3).toMs() }, opts));
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
console.log("posthog disabled");
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
function shutdown() {
|
|
61
|
-
posthog === null || posthog === void 0 ? void 0 : posthog.shutdown();
|
|
62
|
-
}
|
|
63
|
-
class Flag {
|
|
64
|
-
static boolean(defaultValue) {
|
|
65
|
-
return new BooleanFlag(defaultValue);
|
|
66
|
-
}
|
|
67
|
-
static string(defaultValue) {
|
|
68
|
-
return new StringFlag(defaultValue);
|
|
69
|
-
}
|
|
70
|
-
static number(defaultValue) {
|
|
71
|
-
return new NumberFlag(defaultValue);
|
|
72
|
-
}
|
|
73
|
-
constructor(defaultValue) {
|
|
74
|
-
this.defaultValue = defaultValue;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
exports.Flag = Flag;
|
|
78
|
-
class BooleanFlag extends Flag {
|
|
79
|
-
parse(value) {
|
|
80
|
-
if (typeof value === "string") {
|
|
81
|
-
return ["true", "t", "1"].includes(value.toLowerCase());
|
|
82
|
-
}
|
|
83
|
-
if (typeof value === "boolean") {
|
|
84
|
-
return value;
|
|
85
|
-
}
|
|
86
|
-
throw new Error(`could not parse value "${value}" as boolean`);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
class StringFlag extends Flag {
|
|
90
|
-
parse(value) {
|
|
91
|
-
if (typeof value === "string") {
|
|
92
|
-
return value;
|
|
93
|
-
}
|
|
94
|
-
throw new Error(`could not parse value "${value}" as string`);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
class NumberFlag extends Flag {
|
|
98
|
-
parse(value) {
|
|
99
|
-
if (typeof value === "number") {
|
|
100
|
-
return value;
|
|
101
|
-
}
|
|
102
|
-
if (typeof value === "string") {
|
|
103
|
-
const parsed = parseFloat(value);
|
|
104
|
-
if (!isNaN(parsed)) {
|
|
105
|
-
return parsed;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
throw new Error(`could not parse value "${value}" as number`);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
class FlagSet {
|
|
112
|
-
constructor(flagSchema) {
|
|
113
|
-
this.flagSchema = flagSchema;
|
|
114
|
-
this.setId = crypto.randomUUID();
|
|
115
|
-
}
|
|
116
|
-
defaults() {
|
|
117
|
-
return Object.keys(this.flagSchema).reduce((acc, key) => {
|
|
118
|
-
const typedKey = key;
|
|
119
|
-
acc[typedKey] = this.flagSchema[key].defaultValue;
|
|
120
|
-
return acc;
|
|
121
|
-
}, {});
|
|
122
|
-
}
|
|
123
|
-
isFlagName(name) {
|
|
124
|
-
return this.flagSchema[name] !== undefined;
|
|
125
|
-
}
|
|
126
|
-
get(key, ctx) {
|
|
127
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
128
|
-
const flags = yield this.fetch(ctx);
|
|
129
|
-
return flags[key];
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
isEnabled(key, ctx) {
|
|
133
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
134
|
-
const flags = yield this.fetch(ctx);
|
|
135
|
-
return flags[key];
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
fetch(ctx) {
|
|
139
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
140
|
-
return yield dd_trace_1.default.trace("features.fetch", (span) => __awaiter(this, void 0, void 0, function* () {
|
|
141
|
-
var _a, _b;
|
|
142
|
-
const cachedFlags = context.getFeatureFlags(this.setId);
|
|
143
|
-
if (cachedFlags) {
|
|
144
|
-
span === null || span === void 0 ? void 0 : span.addTags({ fromCache: true });
|
|
145
|
-
return cachedFlags;
|
|
146
|
-
}
|
|
147
|
-
const tags = {};
|
|
148
|
-
const flagValues = this.defaults();
|
|
149
|
-
const currentTenantId = context.getTenantId();
|
|
150
|
-
const specificallySetFalse = new Set();
|
|
151
|
-
const split = (environment_1.default.TENANT_FEATURE_FLAGS || "")
|
|
152
|
-
.split(",")
|
|
153
|
-
.map(x => x.split(":"));
|
|
154
|
-
for (const [tenantId, ...features] of split) {
|
|
155
|
-
if (!tenantId || (tenantId !== "*" && tenantId !== currentTenantId)) {
|
|
156
|
-
continue;
|
|
157
|
-
}
|
|
158
|
-
tags[`readFromEnvironmentVars`] = true;
|
|
159
|
-
for (let feature of features) {
|
|
160
|
-
let value = true;
|
|
161
|
-
if (feature.startsWith("!")) {
|
|
162
|
-
feature = feature.slice(1);
|
|
163
|
-
value = false;
|
|
164
|
-
specificallySetFalse.add(feature);
|
|
165
|
-
}
|
|
166
|
-
// ignore unknown flags
|
|
167
|
-
if (!this.isFlagName(feature)) {
|
|
168
|
-
continue;
|
|
169
|
-
}
|
|
170
|
-
if (typeof flagValues[feature] !== "boolean") {
|
|
171
|
-
throw new Error(`Feature: ${feature} is not a boolean`);
|
|
172
|
-
}
|
|
173
|
-
// @ts-expect-error - TS does not like you writing into a generic type,
|
|
174
|
-
// but we know that it's okay in this case because it's just an object.
|
|
175
|
-
flagValues[feature] = value;
|
|
176
|
-
tags[`flags.${feature}.source`] = "environment";
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
const license = (_a = ctx === null || ctx === void 0 ? void 0 : ctx.user) === null || _a === void 0 ? void 0 : _a.license;
|
|
180
|
-
if (license) {
|
|
181
|
-
tags[`readFromLicense`] = true;
|
|
182
|
-
for (const feature of license.features) {
|
|
183
|
-
if (!this.isFlagName(feature)) {
|
|
184
|
-
continue;
|
|
185
|
-
}
|
|
186
|
-
if (flagValues[feature] === true ||
|
|
187
|
-
specificallySetFalse.has(feature)) {
|
|
188
|
-
// If the flag is already set to through environment variables, we
|
|
189
|
-
// don't want to override it back to false here.
|
|
190
|
-
continue;
|
|
191
|
-
}
|
|
192
|
-
// @ts-expect-error - TS does not like you writing into a generic type,
|
|
193
|
-
// but we know that it's okay in this case because it's just an object.
|
|
194
|
-
flagValues[feature] = true;
|
|
195
|
-
tags[`flags.${feature}.source`] = "license";
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
const identity = context.getIdentity();
|
|
199
|
-
tags[`identity.type`] = identity === null || identity === void 0 ? void 0 : identity.type;
|
|
200
|
-
tags[`identity.tenantId`] = identity === null || identity === void 0 ? void 0 : identity.tenantId;
|
|
201
|
-
tags[`identity._id`] = identity === null || identity === void 0 ? void 0 : identity._id;
|
|
202
|
-
if (posthog && (identity === null || identity === void 0 ? void 0 : identity.type) === types_1.IdentityType.USER) {
|
|
203
|
-
tags[`readFromPostHog`] = true;
|
|
204
|
-
const personProperties = {};
|
|
205
|
-
if (identity.tenantId) {
|
|
206
|
-
personProperties.tenantId = identity.tenantId;
|
|
207
|
-
}
|
|
208
|
-
const posthogFlags = yield posthog.getAllFlagsAndPayloads(identity._id, {
|
|
209
|
-
personProperties,
|
|
210
|
-
});
|
|
211
|
-
for (const [name, value] of Object.entries(posthogFlags.featureFlags)) {
|
|
212
|
-
if (!this.isFlagName(name)) {
|
|
213
|
-
// We don't want an unexpected PostHog flag to break the app, so we
|
|
214
|
-
// just log it and continue.
|
|
215
|
-
console.warn(`Unexpected posthog flag "${name}": ${value}`);
|
|
216
|
-
continue;
|
|
217
|
-
}
|
|
218
|
-
if (flagValues[name] === true || specificallySetFalse.has(name)) {
|
|
219
|
-
// If the flag is already set to through environment variables, we
|
|
220
|
-
// don't want to override it back to false here.
|
|
221
|
-
continue;
|
|
222
|
-
}
|
|
223
|
-
const payload = (_b = posthogFlags.featureFlagPayloads) === null || _b === void 0 ? void 0 : _b[name];
|
|
224
|
-
const flag = this.flagSchema[name];
|
|
225
|
-
try {
|
|
226
|
-
// @ts-expect-error - TS does not like you writing into a generic
|
|
227
|
-
// type, but we know that it's okay in this case because it's just
|
|
228
|
-
// an object.
|
|
229
|
-
flagValues[name] = flag.parse(payload || value);
|
|
230
|
-
tags[`flags.${name}.source`] = "posthog";
|
|
231
|
-
}
|
|
232
|
-
catch (err) {
|
|
233
|
-
// We don't want an invalid PostHog flag to break the app, so we just
|
|
234
|
-
// log it and continue.
|
|
235
|
-
console.warn(`Error parsing posthog flag "${name}": ${value}`, err);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
context.setFeatureFlags(this.setId, flagValues);
|
|
240
|
-
for (const [key, value] of Object.entries(flagValues)) {
|
|
241
|
-
tags[`flags.${key}.value`] = value;
|
|
242
|
-
}
|
|
243
|
-
span === null || span === void 0 ? void 0 : span.addTags(tags);
|
|
244
|
-
return flagValues;
|
|
245
|
-
}));
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
exports.FlagSet = FlagSet;
|
|
250
|
-
// This is the primary source of truth for feature flags. If you want to add a
|
|
251
|
-
// new flag, add it here and use the `fetch` and `get` functions to access it.
|
|
252
|
-
// All of the machinery in this file is to make sure that flags have their
|
|
253
|
-
// default values set correctly and their types flow through the system.
|
|
254
|
-
exports.flags = new FlagSet({
|
|
255
|
-
DEFAULT_VALUES: Flag.boolean(environment_1.default.isDev()),
|
|
256
|
-
AUTOMATION_BRANCHING: Flag.boolean(environment_1.default.isDev()),
|
|
257
|
-
SQS: Flag.boolean(environment_1.default.isDev()),
|
|
258
|
-
[types_1.FeatureFlag.AI_CUSTOM_CONFIGS]: Flag.boolean(environment_1.default.isDev()),
|
|
259
|
-
[types_1.FeatureFlag.ENRICHED_RELATIONSHIPS]: Flag.boolean(environment_1.default.isDev()),
|
|
260
|
-
});
|
|
29
|
+
exports.testutils = void 0;
|
|
30
|
+
__exportStar(require("./features"), exports);
|
|
31
|
+
exports.testutils = __importStar(require("./tests/utils"));
|
|
261
32
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/features/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/features/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6CAA0B;AAC1B,2DAA0C"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setFeatureFlags = setFeatureFlags;
|
|
4
|
+
exports.withFeatureFlags = withFeatureFlags;
|
|
5
|
+
const __1 = require("..");
|
|
6
|
+
const environment_1 = require("../../environment");
|
|
7
|
+
function getCurrentFlags() {
|
|
8
|
+
const result = {};
|
|
9
|
+
for (const { tenantId, key, value } of (0, __1.parseEnvFlags)(process.env.TENANT_FEATURE_FLAGS || "")) {
|
|
10
|
+
const tenantFlags = result[tenantId] || {};
|
|
11
|
+
// Don't allow overwriting specifically false flags, to match the beheaviour
|
|
12
|
+
// of FlagSet.
|
|
13
|
+
if (tenantFlags[key] === false) {
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
tenantFlags[key] = value;
|
|
17
|
+
result[tenantId] = tenantFlags;
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
function buildFlagString(flags) {
|
|
22
|
+
const parts = [];
|
|
23
|
+
for (const [tenantId, tenantFlags] of Object.entries(flags)) {
|
|
24
|
+
for (const [key, value] of Object.entries(tenantFlags)) {
|
|
25
|
+
if (value === false) {
|
|
26
|
+
parts.push(`${tenantId}:!${key}`);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
parts.push(`${tenantId}:${key}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return parts.join(",");
|
|
34
|
+
}
|
|
35
|
+
function setFeatureFlags(tenantId, flags) {
|
|
36
|
+
const current = getCurrentFlags();
|
|
37
|
+
for (const [key, value] of Object.entries(flags)) {
|
|
38
|
+
const tenantFlags = current[tenantId] || {};
|
|
39
|
+
tenantFlags[key] = value;
|
|
40
|
+
current[tenantId] = tenantFlags;
|
|
41
|
+
}
|
|
42
|
+
const flagString = buildFlagString(current);
|
|
43
|
+
return (0, environment_1.setEnv)({ TENANT_FEATURE_FLAGS: flagString });
|
|
44
|
+
}
|
|
45
|
+
function withFeatureFlags(tenantId, flags, f) {
|
|
46
|
+
const cleanup = setFeatureFlags(tenantId, flags);
|
|
47
|
+
const result = f();
|
|
48
|
+
if (result instanceof Promise) {
|
|
49
|
+
return result.finally(cleanup);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
cleanup();
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../src/features/tests/utils.ts"],"names":[],"mappings":";;AAoCA,0CAYC;AAED,4CAaC;AA/DD,0BAAgD;AAChD,mDAA0C;AAE1C,SAAS,eAAe;IACtB,MAAM,MAAM,GAA4C,EAAE,CAAA;IAC1D,KAAK,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,IAAA,iBAAa,EAClD,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,EAAE,CACvC,EAAE,CAAC;QACF,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAA;QAC1C,4EAA4E;QAC5E,cAAc;QACd,IAAI,WAAW,CAAC,GAAG,CAAC,KAAK,KAAK,EAAE,CAAC;YAC/B,SAAQ;QACV,CAAC;QACD,WAAW,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;QACxB,MAAM,CAAC,QAAQ,CAAC,GAAG,WAAW,CAAA;IAChC,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAS,eAAe,CACtB,KAA8C;IAE9C,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5D,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;YACvD,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;gBACpB,KAAK,CAAC,IAAI,CAAC,GAAG,QAAQ,KAAK,GAAG,EAAE,CAAC,CAAA;YACnC,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,IAAI,CAAC,GAAG,QAAQ,IAAI,GAAG,EAAE,CAAC,CAAA;YAClC,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACxB,CAAC;AAED,SAAgB,eAAe,CAC7B,QAAgB,EAChB,KAA4B;IAE5B,MAAM,OAAO,GAAG,eAAe,EAAE,CAAA;IACjC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACjD,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAA;QAC3C,WAAW,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;QACxB,OAAO,CAAC,QAAQ,CAAC,GAAG,WAAW,CAAA;IACjC,CAAC;IACD,MAAM,UAAU,GAAG,eAAe,CAAC,OAAO,CAAC,CAAA;IAC3C,OAAO,IAAA,oBAAM,EAAC,EAAE,oBAAoB,EAAE,UAAU,EAAE,CAAC,CAAA;AACrD,CAAC;AAED,SAAgB,gBAAgB,CAC9B,QAAgB,EAChB,KAA4B,EAC5B,CAAU;IAEV,MAAM,OAAO,GAAG,eAAe,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;IAChD,MAAM,MAAM,GAAG,CAAC,EAAE,CAAA;IAClB,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;QAC9B,OAAO,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAChC,CAAC;SAAM,CAAC;QACN,OAAO,EAAE,CAAA;QACT,OAAO,MAAM,CAAA;IACf,CAAC;AACH,CAAC"}
|