next-evolve 0.1.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -1
- package/dist/_virtual/_rolldown/runtime.js +12 -0
- package/dist/aggregate/attribution.d.ts +40 -0
- package/dist/aggregate/attribution.js +115 -0
- package/dist/aggregate/run.d.ts +21 -0
- package/dist/aggregate/run.js +139 -0
- package/dist/cli/aggregate.d.ts +9 -0
- package/dist/cli/aggregate.js +104 -0
- package/dist/cli/args.d.ts +12 -0
- package/dist/cli/args.js +23 -0
- package/dist/cli/cloud.d.ts +41 -0
- package/dist/cli/cloud.js +74 -0
- package/dist/cli/connect.d.ts +8 -0
- package/dist/cli/connect.js +46 -0
- package/dist/cli/detect.d.ts +26 -0
- package/dist/cli/detect.js +97 -0
- package/dist/cli/doctor.d.ts +34 -0
- package/dist/cli/doctor.js +230 -0
- package/dist/cli/env-file.d.ts +4 -0
- package/dist/cli/env-file.js +15 -0
- package/dist/cli/files.d.ts +25 -0
- package/dist/cli/files.js +173 -0
- package/dist/cli/index.js +73 -32
- package/dist/cli/init.d.ts +26 -0
- package/dist/cli/init.js +240 -0
- package/dist/cli/load-app.d.ts +19 -0
- package/dist/cli/load-app.js +67 -0
- package/dist/cli/migrate.d.ts +7 -0
- package/dist/cli/migrate.js +30 -0
- package/dist/cli/pages.d.ts +17 -0
- package/dist/cli/pages.js +304 -0
- package/dist/cli/plan.d.ts +27 -0
- package/dist/cli/plan.js +129 -0
- package/dist/cli/pull.d.ts +13 -0
- package/dist/cli/pull.js +62 -0
- package/dist/cli/push.d.ts +14 -0
- package/dist/cli/push.js +33 -0
- package/dist/cloud/manifest.d.ts +2 -0
- package/dist/cloud/manifest.js +6 -2
- package/dist/core/assign.d.ts +13 -1
- package/dist/core/assign.js +25 -3
- package/dist/db/writer.d.ts +2 -0
- package/dist/db/writer.js +1 -1
- package/dist/instrumentation/index.d.ts +3 -2
- package/dist/instrumentation/index.js +17 -2
- package/dist/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/typescript.d.ts +11169 -0
- package/dist/proxy/index.d.ts +2 -2
- package/dist/proxy/index.js +1 -1
- package/dist/proxy/proxy.d.ts +7 -1
- package/dist/proxy/proxy.js +23 -6
- package/dist/react/render-bundle.d.ts +10 -4
- package/dist/react/render-bundle.js +34 -5
- package/dist/server/aggregate-route.d.ts +16 -0
- package/dist/server/aggregate-route.js +68 -0
- package/dist/server/collect.d.ts +16 -0
- package/dist/server/collect.js +34 -8
- package/dist/server/handler.d.ts +3 -2
- package/dist/server/handler.js +37 -4
- package/dist/server/sync-route.d.ts +28 -0
- package/dist/server/sync-route.js +100 -0
- package/dist/store/disk.d.ts +6 -0
- package/dist/store/disk.js +23 -0
- package/dist/store/fetch.d.ts +4 -0
- package/dist/store/fetch.js +36 -1
- package/dist/store/global-config.d.ts +39 -0
- package/dist/store/global-config.js +122 -0
- package/dist/store/memory.d.ts +11 -2
- package/dist/store/memory.js +6 -2
- package/dist/store/runtime.d.ts +14 -0
- package/dist/store/runtime.js +39 -7
- package/package.json +2 -1
package/dist/core/assign.js
CHANGED
|
@@ -15,6 +15,28 @@ function weightedPick(variants, r) {
|
|
|
15
15
|
return last;
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
|
+
* Deterministic draws for one visitor: the same `evolve_id` and experiment give
|
|
19
|
+
* the same assignment on every request, so concurrent first requests (a link
|
|
20
|
+
* prefetch and the click that follows) can't assign different variants.
|
|
21
|
+
* FNV-1a with a murmur3 finalizer; uniform enough for traffic splits, not crypto.
|
|
22
|
+
*/
|
|
23
|
+
function visitorDraw(anonId) {
|
|
24
|
+
return (key) => {
|
|
25
|
+
let h = 2166136261;
|
|
26
|
+
const s = `${anonId}|${key}`;
|
|
27
|
+
for (let i = 0; i < s.length; i++) {
|
|
28
|
+
h ^= s.charCodeAt(i);
|
|
29
|
+
h = Math.imul(h, 16777619);
|
|
30
|
+
}
|
|
31
|
+
h ^= h >>> 16;
|
|
32
|
+
h = Math.imul(h, 2246822507);
|
|
33
|
+
h ^= h >>> 13;
|
|
34
|
+
h = Math.imul(h, 3266489909);
|
|
35
|
+
h ^= h >>> 16;
|
|
36
|
+
return (h >>> 0) / 4294967296;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
18
40
|
* Assigns a visitor to the experiments on `path` (spec §6.3). Pure: no I/O.
|
|
19
41
|
* Sticky: an active assignment is kept. Completed experiments render their
|
|
20
42
|
* winner and aren't counted. Cookie entries for experiments no longer in the
|
|
@@ -56,7 +78,7 @@ function assign(bundle, path, cookie, rand) {
|
|
|
56
78
|
continue;
|
|
57
79
|
}
|
|
58
80
|
changed = true;
|
|
59
|
-
if (rand() >= e.traffic) {
|
|
81
|
+
if (rand(`${exp}:t`) >= e.traffic) {
|
|
60
82
|
assigned.set(exp, "x");
|
|
61
83
|
pairs.push({
|
|
62
84
|
exp,
|
|
@@ -65,7 +87,7 @@ function assign(bundle, path, cookie, rand) {
|
|
|
65
87
|
});
|
|
66
88
|
continue;
|
|
67
89
|
}
|
|
68
|
-
const v = weightedPick(e.variants, rand());
|
|
90
|
+
const v = weightedPick(e.variants, rand(`${exp}:v`));
|
|
69
91
|
assigned.set(exp, v);
|
|
70
92
|
pairs.push({
|
|
71
93
|
exp,
|
|
@@ -79,4 +101,4 @@ function assign(bundle, path, cookie, rand) {
|
|
|
79
101
|
changed
|
|
80
102
|
};
|
|
81
103
|
}
|
|
82
|
-
export { assign, weightedPick };
|
|
104
|
+
export { assign, visitorDraw, weightedPick };
|
package/dist/db/writer.d.ts
CHANGED
package/dist/db/writer.js
CHANGED
|
@@ -46,7 +46,7 @@ function createWriter(opts) {
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
async function write(sql, batch) {
|
|
49
|
-
for (const rows of chunks(batch.exposures)) await sql`insert into evolve.exposures ${sql(rows, "experiment_id", "anon_id", "variant_id", "path")}
|
|
49
|
+
for (const rows of chunks(batch.exposures)) await sql`insert into evolve.exposures ${sql(rows, "experiment_id", "anon_id", "variant_id", "path", "first_at")}
|
|
50
50
|
on conflict do nothing`;
|
|
51
51
|
for (const rows of chunks(batch.events)) await sql`insert into evolve.events ${sql(rows.map((r) => ({
|
|
52
52
|
...r,
|
|
@@ -15,8 +15,9 @@ export type RegisterEvolveOptions = {
|
|
|
15
15
|
* }
|
|
16
16
|
*
|
|
17
17
|
* Registers the goals for this process and pushes the manifest to the cloud
|
|
18
|
-
* (goals, routes, versions, app URL; spec §8.4), once per process.
|
|
19
|
-
*
|
|
18
|
+
* (goals, routes, versions, app URL; spec §8.4), once per process. On
|
|
19
|
+
* long-running Node it also polls the bundle in the background (spec §7.5),
|
|
20
|
+
* so the disk cache stays fresh between requests. Never throws.
|
|
20
21
|
*/
|
|
21
22
|
export declare function registerEvolve(opts: RegisterEvolveOptions): Promise<void>;
|
|
22
23
|
/** Test helper. */
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { buildManifest, detectAppUrl } from "../cloud/manifest.js";
|
|
2
2
|
import { pushToCloud } from "../cloud/push.js";
|
|
3
|
+
import { resolveConfig } from "../config/config.js";
|
|
3
4
|
import { setRuntime } from "../server/runtime.js";
|
|
5
|
+
import { getBundleStore, isLongRunningNode } from "../store/runtime.js";
|
|
4
6
|
// src/instrumentation/index.ts
|
|
5
7
|
let registered = false;
|
|
8
|
+
let poll = null;
|
|
6
9
|
/**
|
|
7
10
|
* Call from `instrumentation.ts` `register()`:
|
|
8
11
|
*
|
|
@@ -14,8 +17,9 @@ let registered = false;
|
|
|
14
17
|
* }
|
|
15
18
|
*
|
|
16
19
|
* Registers the goals for this process and pushes the manifest to the cloud
|
|
17
|
-
* (goals, routes, versions, app URL; spec §8.4), once per process.
|
|
18
|
-
*
|
|
20
|
+
* (goals, routes, versions, app URL; spec §8.4), once per process. On
|
|
21
|
+
* long-running Node it also polls the bundle in the background (spec §7.5),
|
|
22
|
+
* so the disk cache stays fresh between requests. Never throws.
|
|
19
23
|
*/
|
|
20
24
|
async function registerEvolve(opts) {
|
|
21
25
|
if (registered) return;
|
|
@@ -25,6 +29,15 @@ async function registerEvolve(opts) {
|
|
|
25
29
|
config: opts.config,
|
|
26
30
|
goals: opts.goals
|
|
27
31
|
});
|
|
32
|
+
if (isLongRunningNode()) {
|
|
33
|
+
const cfg = resolveConfig(opts.config);
|
|
34
|
+
const store = getBundleStore(cfg);
|
|
35
|
+
if (store) {
|
|
36
|
+
store.refresh();
|
|
37
|
+
poll = setInterval(() => void store.refresh(), cfg.pollSeconds * 1e3);
|
|
38
|
+
poll.unref();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
28
41
|
const manifest = buildManifest(opts.config, opts.goals, { appUrl: detectAppUrl() });
|
|
29
42
|
const res = await pushToCloud("/v1/manifest", manifest);
|
|
30
43
|
if (!res.ok && res.status !== "no_key") console.error(`[evolve] manifest push failed (${res.status})`);
|
|
@@ -35,5 +48,7 @@ async function registerEvolve(opts) {
|
|
|
35
48
|
/** Test helper. */
|
|
36
49
|
function resetRegisterEvolve() {
|
|
37
50
|
registered = false;
|
|
51
|
+
if (poll) clearInterval(poll);
|
|
52
|
+
poll = null;
|
|
38
53
|
}
|
|
39
54
|
export { registerEvolve, resetRegisterEvolve };
|