praetom 0.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/README.md +82 -0
- package/dist/_esm-loader.d.ts +49 -0
- package/dist/_esm-loader.d.ts.map +1 -0
- package/dist/_esm-loader.js +131 -0
- package/dist/_esm-loader.js.map +1 -0
- package/dist/_internal.d.ts +63 -0
- package/dist/_internal.d.ts.map +1 -0
- package/dist/_internal.js +357 -0
- package/dist/_internal.js.map +1 -0
- package/dist/browser.d.ts +90 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +357 -0
- package/dist/browser.js.map +1 -0
- package/dist/cli/cli.d.ts +3 -0
- package/dist/cli/cli.d.ts.map +1 -0
- package/dist/cli/cli.js +97 -0
- package/dist/cli/cli.js.map +1 -0
- package/dist/cli/commands/discover.d.ts +3 -0
- package/dist/cli/commands/discover.d.ts.map +1 -0
- package/dist/cli/commands/discover.js +15 -0
- package/dist/cli/commands/discover.js.map +1 -0
- package/dist/cli/commands/features.d.ts +5 -0
- package/dist/cli/commands/features.d.ts.map +1 -0
- package/dist/cli/commands/features.js +83 -0
- package/dist/cli/commands/features.js.map +1 -0
- package/dist/cli/commands/init.d.ts +3 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +52 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/login.d.ts +20 -0
- package/dist/cli/commands/login.d.ts.map +1 -0
- package/dist/cli/commands/login.js +138 -0
- package/dist/cli/commands/login.js.map +1 -0
- package/dist/cli/commands/logout.d.ts +3 -0
- package/dist/cli/commands/logout.d.ts.map +1 -0
- package/dist/cli/commands/logout.js +15 -0
- package/dist/cli/commands/logout.js.map +1 -0
- package/dist/cli/commands/rotate.d.ts +3 -0
- package/dist/cli/commands/rotate.d.ts.map +1 -0
- package/dist/cli/commands/rotate.js +33 -0
- package/dist/cli/commands/rotate.js.map +1 -0
- package/dist/cli/commands/status.d.ts +3 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +54 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/uninstall.d.ts +3 -0
- package/dist/cli/commands/uninstall.d.ts.map +1 -0
- package/dist/cli/commands/uninstall.js +63 -0
- package/dist/cli/commands/uninstall.js.map +1 -0
- package/dist/cli/commands/usage.d.ts +3 -0
- package/dist/cli/commands/usage.d.ts.map +1 -0
- package/dist/cli/commands/usage.js +19 -0
- package/dist/cli/commands/usage.js.map +1 -0
- package/dist/cli/commands/whoami.d.ts +3 -0
- package/dist/cli/commands/whoami.d.ts.map +1 -0
- package/dist/cli/commands/whoami.js +37 -0
- package/dist/cli/commands/whoami.js.map +1 -0
- package/dist/cli/util/agent-env.d.ts +13 -0
- package/dist/cli/util/agent-env.d.ts.map +1 -0
- package/dist/cli/util/agent-env.js +28 -0
- package/dist/cli/util/agent-env.js.map +1 -0
- package/dist/cli/util/api.d.ts +36 -0
- package/dist/cli/util/api.d.ts.map +1 -0
- package/dist/cli/util/api.js +84 -0
- package/dist/cli/util/api.js.map +1 -0
- package/dist/cli/util/auth-file.d.ts +25 -0
- package/dist/cli/util/auth-file.d.ts.map +1 -0
- package/dist/cli/util/auth-file.js +74 -0
- package/dist/cli/util/auth-file.js.map +1 -0
- package/dist/cli/util/git.d.ts +28 -0
- package/dist/cli/util/git.d.ts.map +1 -0
- package/dist/cli/util/git.js +103 -0
- package/dist/cli/util/git.js.map +1 -0
- package/dist/cli/util/run.d.ts +26 -0
- package/dist/cli/util/run.d.ts.map +1 -0
- package/dist/cli/util/run.js +31 -0
- package/dist/cli/util/run.js.map +1 -0
- package/dist/edge.d.ts +34 -0
- package/dist/edge.d.ts.map +1 -0
- package/dist/edge.js +127 -0
- package/dist/edge.js.map +1 -0
- package/dist/server.d.ts +69 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +193 -0
- package/dist/server.js.map +1 -0
- package/dist/vite/index.d.ts +48 -0
- package/dist/vite/index.d.ts.map +1 -0
- package/dist/vite/index.js +138 -0
- package/dist/vite/index.js.map +1 -0
- package/dist/webpack/index.d.ts +64 -0
- package/dist/webpack/index.d.ts.map +1 -0
- package/dist/webpack/index.js +106 -0
- package/dist/webpack/index.js.map +1 -0
- package/dist/webpack/loader.d.ts +27 -0
- package/dist/webpack/loader.d.ts.map +1 -0
- package/dist/webpack/loader.js +54 -0
- package/dist/webpack/loader.js.map +1 -0
- package/dist/webpack/shared.d.ts +25 -0
- package/dist/webpack/shared.d.ts.map +1 -0
- package/dist/webpack/shared.js +63 -0
- package/dist/webpack/shared.js.map +1 -0
- package/package.json +79 -0
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* praetom — the server-side customer API.
|
|
3
|
+
*
|
|
4
|
+
* Two exports, that's it:
|
|
5
|
+
* - register({ ingestId }) — call once at process start
|
|
6
|
+
* - emit(eventName, payload?) — fire a point-in-time event from
|
|
7
|
+
* inside business logic
|
|
8
|
+
*
|
|
9
|
+
* // In Next.js: apps/web/instrumentation.ts
|
|
10
|
+
* import { register } from "praetom";
|
|
11
|
+
* await register();
|
|
12
|
+
*
|
|
13
|
+
* // In Express / Fastify / raw Node: top of the entry point
|
|
14
|
+
* import { register } from "praetom";
|
|
15
|
+
* register();
|
|
16
|
+
*
|
|
17
|
+
* // Anywhere inside a feature's code, to mark a sub-event:
|
|
18
|
+
* import { emit } from "praetom";
|
|
19
|
+
* emit("checkout:stripe-charged", { amount });
|
|
20
|
+
*
|
|
21
|
+
* What register() does on boot:
|
|
22
|
+
* 1. Reads PRAETOM_INGEST_ID from env (or accepts via options). The
|
|
23
|
+
* token encodes both the workspace AND the repo it represents —
|
|
24
|
+
* same shape as a Sentry DSN.
|
|
25
|
+
* 2. Calls praetom.com/api/runtime/config; the server resolves the
|
|
26
|
+
* repo from the bearer token and returns its feature map.
|
|
27
|
+
* 3. Installs a Module._load hook (CJS) that wraps the entry_symbol
|
|
28
|
+
* of any file matching a feature's primary_path list.
|
|
29
|
+
*
|
|
30
|
+
* praetom's DB is the source of truth for what gets wrapped — there
|
|
31
|
+
* are NO feature(slug, fn) wraps in customer source code. Discovery
|
|
32
|
+
* defines features in praetom; the runtime applies them at boot.
|
|
33
|
+
*
|
|
34
|
+
* What's not yet covered by the runtime hooks alone:
|
|
35
|
+
* - Bundled apps (Next.js prod, Vite/Rollup builds, etc.) — files are
|
|
36
|
+
* concatenated into chunks, so neither Module._load nor the ESM
|
|
37
|
+
* loader sees them as individual modules. Use the bundler plugins
|
|
38
|
+
* (`praetom/vite`, `praetom/webpack`) for those — they wrap at
|
|
39
|
+
* build time.
|
|
40
|
+
* - Live map updates. v1 fetches once on boot. SSE subscription is
|
|
41
|
+
* a follow-up.
|
|
42
|
+
*/
|
|
43
|
+
import { emit, wrapEntryPoint } from "./_internal";
|
|
44
|
+
export interface RegisterOptions {
|
|
45
|
+
/** Override the ingest token (defaults to PRAETOM_INGEST_ID env var). */
|
|
46
|
+
ingestId?: string;
|
|
47
|
+
/** Override the OTLP endpoint (defaults to praetom.com). */
|
|
48
|
+
endpoint?: string;
|
|
49
|
+
/** Override the config endpoint (defaults to praetom.com). */
|
|
50
|
+
configEndpoint?: string;
|
|
51
|
+
/** Suppress the boot-time console.warn lines (for tests). */
|
|
52
|
+
silent?: boolean;
|
|
53
|
+
}
|
|
54
|
+
export declare function register(opts?: RegisterOptions): Promise<void>;
|
|
55
|
+
export { emit };
|
|
56
|
+
/**
|
|
57
|
+
* Internal escape hatch for bundler-plugin-generated code. NOT a public
|
|
58
|
+
* customer API — the leading underscores signal "compile-time only;
|
|
59
|
+
* customers should never import this." The bundler plugin injects calls
|
|
60
|
+
* like `__praetomWrapEntryPoint("checkout", "POST", originalHandler)`
|
|
61
|
+
* into transformed source.
|
|
62
|
+
*/
|
|
63
|
+
export declare const __praetomWrapEntryPoint: typeof wrapEntryPoint;
|
|
64
|
+
/**
|
|
65
|
+
* Test-only — clear the registered map between unit tests. Customers
|
|
66
|
+
* don't call this in production.
|
|
67
|
+
*/
|
|
68
|
+
export declare function _resetForTests(): void;
|
|
69
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAKH,OAAO,EAAE,IAAI,EAAQ,cAAc,EAAE,MAAM,aAAa,CAAC;AAuBzD,MAAM,WAAW,eAAe;IAC9B,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAID,wBAAsB,QAAQ,CAAC,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwDxE;AA4GD,OAAO,EAAE,IAAI,EAAE,CAAC;AAEhB;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,uBAAiB,CAAC;AAEtD;;;GAGG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAGrC"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* praetom — the server-side customer API.
|
|
3
|
+
*
|
|
4
|
+
* Two exports, that's it:
|
|
5
|
+
* - register({ ingestId }) — call once at process start
|
|
6
|
+
* - emit(eventName, payload?) — fire a point-in-time event from
|
|
7
|
+
* inside business logic
|
|
8
|
+
*
|
|
9
|
+
* // In Next.js: apps/web/instrumentation.ts
|
|
10
|
+
* import { register } from "praetom";
|
|
11
|
+
* await register();
|
|
12
|
+
*
|
|
13
|
+
* // In Express / Fastify / raw Node: top of the entry point
|
|
14
|
+
* import { register } from "praetom";
|
|
15
|
+
* register();
|
|
16
|
+
*
|
|
17
|
+
* // Anywhere inside a feature's code, to mark a sub-event:
|
|
18
|
+
* import { emit } from "praetom";
|
|
19
|
+
* emit("checkout:stripe-charged", { amount });
|
|
20
|
+
*
|
|
21
|
+
* What register() does on boot:
|
|
22
|
+
* 1. Reads PRAETOM_INGEST_ID from env (or accepts via options). The
|
|
23
|
+
* token encodes both the workspace AND the repo it represents —
|
|
24
|
+
* same shape as a Sentry DSN.
|
|
25
|
+
* 2. Calls praetom.com/api/runtime/config; the server resolves the
|
|
26
|
+
* repo from the bearer token and returns its feature map.
|
|
27
|
+
* 3. Installs a Module._load hook (CJS) that wraps the entry_symbol
|
|
28
|
+
* of any file matching a feature's primary_path list.
|
|
29
|
+
*
|
|
30
|
+
* praetom's DB is the source of truth for what gets wrapped — there
|
|
31
|
+
* are NO feature(slug, fn) wraps in customer source code. Discovery
|
|
32
|
+
* defines features in praetom; the runtime applies them at boot.
|
|
33
|
+
*
|
|
34
|
+
* What's not yet covered by the runtime hooks alone:
|
|
35
|
+
* - Bundled apps (Next.js prod, Vite/Rollup builds, etc.) — files are
|
|
36
|
+
* concatenated into chunks, so neither Module._load nor the ESM
|
|
37
|
+
* loader sees them as individual modules. Use the bundler plugins
|
|
38
|
+
* (`praetom/vite`, `praetom/webpack`) for those — they wrap at
|
|
39
|
+
* build time.
|
|
40
|
+
* - Live map updates. v1 fetches once on boot. SSE subscription is
|
|
41
|
+
* a follow-up.
|
|
42
|
+
*/
|
|
43
|
+
import Module from "node:module";
|
|
44
|
+
import { register as registerEsmLoader } from "node:module";
|
|
45
|
+
import { emit, init, wrapEntryPoint } from "./_internal";
|
|
46
|
+
const mapByPath = new Map();
|
|
47
|
+
let _hookInstalled = false;
|
|
48
|
+
const DEFAULT_CONFIG_ENDPOINT = "https://praetom.com/api/runtime/config";
|
|
49
|
+
export async function register(opts = {}) {
|
|
50
|
+
const ingestId = opts.ingestId ?? process.env.PRAETOM_INGEST_ID;
|
|
51
|
+
const warn = opts.silent
|
|
52
|
+
? () => { }
|
|
53
|
+
: (msg) => {
|
|
54
|
+
// eslint-disable-next-line no-console
|
|
55
|
+
console.warn(`[praetom] ${msg}`);
|
|
56
|
+
};
|
|
57
|
+
if (!ingestId) {
|
|
58
|
+
warn("PRAETOM_INGEST_ID not set; instrumentation disabled");
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
// The token encodes (workspace, repo) identity — no PRAETOM_REPO or
|
|
62
|
+
// deploy-provider env vars needed. Just call config; the server resolves
|
|
63
|
+
// the repo from the bearer token.
|
|
64
|
+
let config;
|
|
65
|
+
try {
|
|
66
|
+
const cfgUrl = opts.configEndpoint ?? DEFAULT_CONFIG_ENDPOINT;
|
|
67
|
+
const abort = new AbortController();
|
|
68
|
+
const timer = setTimeout(() => abort.abort(), 5_000);
|
|
69
|
+
const res = await fetch(cfgUrl, {
|
|
70
|
+
headers: { authorization: `Bearer ${ingestId}` },
|
|
71
|
+
signal: abort.signal,
|
|
72
|
+
}).finally(() => clearTimeout(timer));
|
|
73
|
+
if (!res.ok) {
|
|
74
|
+
warn(`runtime/config fetch failed: HTTP ${res.status}`);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
config = (await res.json());
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
warn(`runtime/config fetch error: ${e.message}`);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
init({
|
|
84
|
+
token: ingestId,
|
|
85
|
+
endpoint: opts.endpoint,
|
|
86
|
+
serviceName: config.repo,
|
|
87
|
+
});
|
|
88
|
+
mapByPath.clear();
|
|
89
|
+
for (const f of config.features) {
|
|
90
|
+
for (const p of f.paths) {
|
|
91
|
+
mapByPath.set(p, { slug: f.slug, entrySymbol: f.entrySymbol, side: f.side });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (mapByPath.size === 0) {
|
|
95
|
+
warn(`workspace ${config.workspaceSlug} has no features for ${config.repo}; instrumentation idle`);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
installRequireHook();
|
|
99
|
+
installEsmLoader(warn);
|
|
100
|
+
}
|
|
101
|
+
function installEsmLoader(warn) {
|
|
102
|
+
if (_esmLoaderInstalled)
|
|
103
|
+
return;
|
|
104
|
+
try {
|
|
105
|
+
const loaderUrl = new URL("./_esm-loader.js", import.meta.url);
|
|
106
|
+
registerEsmLoader(loaderUrl.href, import.meta.url, {
|
|
107
|
+
data: {
|
|
108
|
+
featureMap: [...mapByPath.entries()].map(([path, info]) => [
|
|
109
|
+
path,
|
|
110
|
+
{ slug: info.slug, entrySymbol: info.entrySymbol },
|
|
111
|
+
]),
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
_esmLoaderInstalled = true;
|
|
115
|
+
}
|
|
116
|
+
catch (e) {
|
|
117
|
+
warn(`ESM loader registration failed: ${e.message}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
let _esmLoaderInstalled = false;
|
|
121
|
+
function installRequireHook() {
|
|
122
|
+
if (_hookInstalled)
|
|
123
|
+
return;
|
|
124
|
+
const mod = Module;
|
|
125
|
+
const originalLoad = mod._load;
|
|
126
|
+
mod._load = function patchedLoad(request, parent, isMain) {
|
|
127
|
+
const exported = originalLoad.call(this, request, parent, isMain);
|
|
128
|
+
if (!parent || typeof parent.filename !== "string")
|
|
129
|
+
return exported;
|
|
130
|
+
let resolved;
|
|
131
|
+
try {
|
|
132
|
+
resolved = mod._resolveFilename(request, parent, isMain);
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
return exported;
|
|
136
|
+
}
|
|
137
|
+
const match = matchFeatureForPath(resolved);
|
|
138
|
+
if (!match)
|
|
139
|
+
return exported;
|
|
140
|
+
return wrapModuleExports(exported, match);
|
|
141
|
+
};
|
|
142
|
+
_hookInstalled = true;
|
|
143
|
+
}
|
|
144
|
+
function matchFeatureForPath(absolutePath) {
|
|
145
|
+
for (const [featurePath, info] of mapByPath) {
|
|
146
|
+
if (absolutePath === featurePath ||
|
|
147
|
+
absolutePath.endsWith(`/${featurePath}`) ||
|
|
148
|
+
// Windows path support
|
|
149
|
+
absolutePath.replace(/\\/g, "/").endsWith(`/${featurePath}`)) {
|
|
150
|
+
return info;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
function wrapModuleExports(exports, info) {
|
|
156
|
+
if (!exports || (typeof exports !== "object" && typeof exports !== "function")) {
|
|
157
|
+
return exports;
|
|
158
|
+
}
|
|
159
|
+
const e = exports;
|
|
160
|
+
if (info.entrySymbol && typeof e[info.entrySymbol] === "function") {
|
|
161
|
+
e[info.entrySymbol] = wrapEntryPoint(info.slug, info.entrySymbol, e[info.entrySymbol]);
|
|
162
|
+
return exports;
|
|
163
|
+
}
|
|
164
|
+
// No specific entry_symbol — wrap default export if function-shaped,
|
|
165
|
+
// plus any HTTP-method-named exports (Next.js App Router convention).
|
|
166
|
+
if (typeof e.default === "function") {
|
|
167
|
+
e.default = wrapEntryPoint(info.slug, "default", e.default);
|
|
168
|
+
}
|
|
169
|
+
for (const m of ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"]) {
|
|
170
|
+
if (typeof e[m] === "function") {
|
|
171
|
+
e[m] = wrapEntryPoint(info.slug, m, e[m]);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return exports;
|
|
175
|
+
}
|
|
176
|
+
export { emit };
|
|
177
|
+
/**
|
|
178
|
+
* Internal escape hatch for bundler-plugin-generated code. NOT a public
|
|
179
|
+
* customer API — the leading underscores signal "compile-time only;
|
|
180
|
+
* customers should never import this." The bundler plugin injects calls
|
|
181
|
+
* like `__praetomWrapEntryPoint("checkout", "POST", originalHandler)`
|
|
182
|
+
* into transformed source.
|
|
183
|
+
*/
|
|
184
|
+
export const __praetomWrapEntryPoint = wrapEntryPoint;
|
|
185
|
+
/**
|
|
186
|
+
* Test-only — clear the registered map between unit tests. Customers
|
|
187
|
+
* don't call this in production.
|
|
188
|
+
*/
|
|
189
|
+
export function _resetForTests() {
|
|
190
|
+
mapByPath.clear();
|
|
191
|
+
_hookInstalled = false;
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* praetom/vite — Vite/Rollup plugin for praetom.
|
|
3
|
+
*
|
|
4
|
+
* On build start: fetches the workspace's feature map from praetom using
|
|
5
|
+
* the per-repo ingest token. On every file transformed by Vite, checks
|
|
6
|
+
* whether the file's path matches a feature's `paths` list — if so,
|
|
7
|
+
* rewrites the source to wrap each named export with
|
|
8
|
+
* `__praetomWrapEntryPoint(slug, name, original)` from the runtime SDK.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* // vite.config.ts
|
|
12
|
+
* import { defineConfig } from "vite";
|
|
13
|
+
* import praetom from "praetom/vite";
|
|
14
|
+
*
|
|
15
|
+
* export default defineConfig({
|
|
16
|
+
* plugins: [praetom()],
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* Auth: PRAETOM_INGEST_ID env var at build time (typical CI pattern),
|
|
20
|
+
* or pass `{ ingestId: "..." }` as plugin options.
|
|
21
|
+
*
|
|
22
|
+
* The transform is regex-level — same patterns as the runtime ESM
|
|
23
|
+
* loader hook in praetom. Same limitations: handles
|
|
24
|
+
* named-function-shaped exports, falls back to no-op + warning for
|
|
25
|
+
* shapes it doesn't recognize.
|
|
26
|
+
*/
|
|
27
|
+
import type { Plugin } from "vite";
|
|
28
|
+
export interface PraetomViteOptions {
|
|
29
|
+
/**
|
|
30
|
+
* Per-repo ingest token used to fetch the feature map. Defaults to the
|
|
31
|
+
* PRAETOM_INGEST_ID env var. In CI, set the env var; locally, the
|
|
32
|
+
* dotenv loader (if any) feeds it in. As a last resort pass inline.
|
|
33
|
+
*/
|
|
34
|
+
ingestId?: string;
|
|
35
|
+
/** Override the config endpoint. Defaults to https://praetom.com. */
|
|
36
|
+
configEndpoint?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Project root for resolving feature paths. Feature paths come from
|
|
39
|
+
* praetom relative to the *repo* root; if your Vite build runs from
|
|
40
|
+
* inside a workspace package, set this so the plugin can translate.
|
|
41
|
+
* Defaults to the Vite-resolved project root.
|
|
42
|
+
*/
|
|
43
|
+
projectRoot?: string;
|
|
44
|
+
/** Quiet mode — suppress [praetom] warns/info. */
|
|
45
|
+
silent?: boolean;
|
|
46
|
+
}
|
|
47
|
+
export default function praetom(opts?: PraetomViteOptions): Plugin;
|
|
48
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vite/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAenC,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kDAAkD;IAClD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAeD,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,IAAI,GAAE,kBAAuB,GAAG,MAAM,CA6ErE"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* praetom/vite — Vite/Rollup plugin for praetom.
|
|
3
|
+
*
|
|
4
|
+
* On build start: fetches the workspace's feature map from praetom using
|
|
5
|
+
* the per-repo ingest token. On every file transformed by Vite, checks
|
|
6
|
+
* whether the file's path matches a feature's `paths` list — if so,
|
|
7
|
+
* rewrites the source to wrap each named export with
|
|
8
|
+
* `__praetomWrapEntryPoint(slug, name, original)` from the runtime SDK.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* // vite.config.ts
|
|
12
|
+
* import { defineConfig } from "vite";
|
|
13
|
+
* import praetom from "praetom/vite";
|
|
14
|
+
*
|
|
15
|
+
* export default defineConfig({
|
|
16
|
+
* plugins: [praetom()],
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* Auth: PRAETOM_INGEST_ID env var at build time (typical CI pattern),
|
|
20
|
+
* or pass `{ ingestId: "..." }` as plugin options.
|
|
21
|
+
*
|
|
22
|
+
* The transform is regex-level — same patterns as the runtime ESM
|
|
23
|
+
* loader hook in praetom. Same limitations: handles
|
|
24
|
+
* named-function-shaped exports, falls back to no-op + warning for
|
|
25
|
+
* shapes it doesn't recognize.
|
|
26
|
+
*/
|
|
27
|
+
const DEFAULT_CONFIG_ENDPOINT = "https://praetom.com/api/runtime/config";
|
|
28
|
+
const PRAETOM_IMPORT_MARKER = "__praetom_wrap_import__";
|
|
29
|
+
const HTTP_METHODS = new Set([
|
|
30
|
+
"GET",
|
|
31
|
+
"POST",
|
|
32
|
+
"PUT",
|
|
33
|
+
"PATCH",
|
|
34
|
+
"DELETE",
|
|
35
|
+
"OPTIONS",
|
|
36
|
+
"HEAD",
|
|
37
|
+
]);
|
|
38
|
+
export default function praetom(opts = {}) {
|
|
39
|
+
let featureMap = [];
|
|
40
|
+
let projectRoot = "";
|
|
41
|
+
const log = opts.silent
|
|
42
|
+
? () => { }
|
|
43
|
+
: // eslint-disable-next-line no-console
|
|
44
|
+
(msg) => console.warn(`[praetom] ${msg}`);
|
|
45
|
+
return {
|
|
46
|
+
name: "praetom/vite",
|
|
47
|
+
enforce: "pre",
|
|
48
|
+
async buildStart() {
|
|
49
|
+
const token = opts.ingestId ?? process.env.PRAETOM_INGEST_ID;
|
|
50
|
+
if (!token) {
|
|
51
|
+
log("PRAETOM_INGEST_ID not set and no ingestId option passed; build will not auto-wrap any features");
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const url = opts.configEndpoint ?? DEFAULT_CONFIG_ENDPOINT;
|
|
55
|
+
try {
|
|
56
|
+
const res = await fetch(url, {
|
|
57
|
+
headers: { authorization: `Bearer ${token}` },
|
|
58
|
+
});
|
|
59
|
+
if (!res.ok) {
|
|
60
|
+
throw new Error(`runtime/config returned HTTP ${res.status}`);
|
|
61
|
+
}
|
|
62
|
+
const config = (await res.json());
|
|
63
|
+
featureMap = config.features;
|
|
64
|
+
log(`loaded feature map: ${featureMap.length} features in ${config.repo}`);
|
|
65
|
+
}
|
|
66
|
+
catch (e) {
|
|
67
|
+
throw new Error(`[praetom] failed to fetch feature map from ${url}: ${e.message}. ` +
|
|
68
|
+
`Set PRAETOM_INGEST_ID to a valid per-repo token or pass { ingestId } to the plugin.`);
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
configResolved(resolvedConfig) {
|
|
72
|
+
projectRoot = opts.projectRoot ?? resolvedConfig.root;
|
|
73
|
+
},
|
|
74
|
+
transform(code, id) {
|
|
75
|
+
if (featureMap.length === 0)
|
|
76
|
+
return null;
|
|
77
|
+
if (id.includes("/node_modules/"))
|
|
78
|
+
return null;
|
|
79
|
+
if (id.startsWith("\0"))
|
|
80
|
+
return null; // virtual / rolled-up modules
|
|
81
|
+
const relPath = relativeToRoot(id, projectRoot);
|
|
82
|
+
const match = matchFeatureForPath(relPath);
|
|
83
|
+
if (!match)
|
|
84
|
+
return null;
|
|
85
|
+
const wrapped = wrapModuleSource(code, match.slug, match.entrySymbol);
|
|
86
|
+
if (!wrapped) {
|
|
87
|
+
log(`could not wrap ${relPath} (export shape not recognized; skipping)`);
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
return { code: wrapped, map: null };
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
function matchFeatureForPath(relPath) {
|
|
94
|
+
for (const feature of featureMap) {
|
|
95
|
+
if (feature.paths.some((p) => relPath === p || relPath.endsWith(`/${p}`))) {
|
|
96
|
+
return { slug: feature.slug, entrySymbol: feature.entrySymbol };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function relativeToRoot(id, root) {
|
|
103
|
+
const path = id.split("?")[0];
|
|
104
|
+
if (path.startsWith(root)) {
|
|
105
|
+
return path.slice(root.length).replace(/^\//, "");
|
|
106
|
+
}
|
|
107
|
+
return path;
|
|
108
|
+
}
|
|
109
|
+
function shouldWrap(name, entrySymbol) {
|
|
110
|
+
if (entrySymbol)
|
|
111
|
+
return name === entrySymbol;
|
|
112
|
+
return HTTP_METHODS.has(name) || name === "handler";
|
|
113
|
+
}
|
|
114
|
+
function wrapModuleSource(source, slug, entrySymbol) {
|
|
115
|
+
if (source.includes(PRAETOM_IMPORT_MARKER))
|
|
116
|
+
return null;
|
|
117
|
+
const targets = new Set();
|
|
118
|
+
let rewritten = source.replace(/^export\s+(async\s+)?function\s+([A-Za-z_$][\w$]*)\s*\(/gm, (_m, asyncKw, name) => {
|
|
119
|
+
if (!shouldWrap(name, entrySymbol))
|
|
120
|
+
return _m;
|
|
121
|
+
targets.add(name);
|
|
122
|
+
return `${asyncKw ?? ""}function __praetom_orig_${name}(`;
|
|
123
|
+
});
|
|
124
|
+
rewritten = rewritten.replace(/^export\s+const\s+([A-Za-z_$][\w$]*)\s*=/gm, (_m, name) => {
|
|
125
|
+
if (!shouldWrap(name, entrySymbol))
|
|
126
|
+
return _m;
|
|
127
|
+
targets.add(name);
|
|
128
|
+
return `const __praetom_orig_${name} =`;
|
|
129
|
+
});
|
|
130
|
+
if (targets.size === 0)
|
|
131
|
+
return null;
|
|
132
|
+
const importLine = `import { __praetomWrapEntryPoint as ${PRAETOM_IMPORT_MARKER} } from "praetom";\n`;
|
|
133
|
+
const wraps = [...targets]
|
|
134
|
+
.map((name) => `export const ${name} = ${PRAETOM_IMPORT_MARKER}(${JSON.stringify(slug)}, ${JSON.stringify(name)}, __praetom_orig_${name});`)
|
|
135
|
+
.join("\n");
|
|
136
|
+
return `${importLine}${rewritten}\n${wraps}\n`;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/vite/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAqCH,MAAM,uBAAuB,GAAG,wCAAwC,CAAC;AACzE,MAAM,qBAAqB,GAAG,yBAAyB,CAAC;AAExD,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC;IAC3B,KAAK;IACL,MAAM;IACN,KAAK;IACL,OAAO;IACP,QAAQ;IACR,SAAS;IACT,MAAM;CACP,CAAC,CAAC;AAEH,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,OAA2B,EAAE;IAC3D,IAAI,UAAU,GAAsB,EAAE,CAAC;IACvC,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM;QACrB,CAAC,CAAC,GAAG,EAAE,GAAE,CAAC;QACV,CAAC,CAAC,sCAAsC;YACtC,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC,CAAC;IAEtD,OAAO;QACL,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,KAAK;QAEd,KAAK,CAAC,UAAU;YACd,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;YAC7D,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,GAAG,CACD,gGAAgG,CACjG,CAAC;gBACF,OAAO;YACT,CAAC;YACD,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,IAAI,uBAAuB,CAAC;YAC3D,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;oBAC3B,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE;iBAC9C,CAAC,CAAC;gBACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;oBACZ,MAAM,IAAI,KAAK,CACb,gCAAgC,GAAG,CAAC,MAAM,EAAE,CAC7C,CAAC;gBACJ,CAAC;gBACD,MAAM,MAAM,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA0B,CAAC;gBAC3D,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC;gBAC7B,GAAG,CACD,uBAAuB,UAAU,CAAC,MAAM,gBAAgB,MAAM,CAAC,IAAI,EAAE,CACtE,CAAC;YACJ,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,MAAM,IAAI,KAAK,CACb,8CAA8C,GAAG,KAAM,CAAW,CAAC,OAAO,IAAI;oBAC5E,qFAAqF,CACxF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,cAAc,CAAC,cAAc;YAC3B,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,cAAc,CAAC,IAAI,CAAC;QACxD,CAAC;QAED,SAAS,CAAC,IAAI,EAAE,EAAE;YAChB,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;YACzC,IAAI,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC;gBAAE,OAAO,IAAI,CAAC;YAC/C,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;gBAAE,OAAO,IAAI,CAAC,CAAC,8BAA8B;YAEpE,MAAM,OAAO,GAAG,cAAc,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;YAChD,MAAM,KAAK,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;YAC3C,IAAI,CAAC,KAAK;gBAAE,OAAO,IAAI,CAAC;YAExB,MAAM,OAAO,GAAG,gBAAgB,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;YACtE,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,GAAG,CACD,kBAAkB,OAAO,0CAA0C,CACpE,CAAC;gBACF,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;QACtC,CAAC;KACF,CAAC;IAEF,SAAS,mBAAmB,CAC1B,OAAe;QAEf,KAAK,MAAM,OAAO,IAAI,UAAU,EAAE,CAAC;YACjC,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,KAAK,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;gBAC1E,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC;YAClE,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,EAAU,EAAE,IAAY;IAC9C,MAAM,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;IAC/B,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,WAA+B;IAC/D,IAAI,WAAW;QAAE,OAAO,IAAI,KAAK,WAAW,CAAC;IAC7C,OAAO,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,KAAK,SAAS,CAAC;AACtD,CAAC;AAED,SAAS,gBAAgB,CACvB,MAAc,EACd,IAAY,EACZ,WAAoB;IAEpB,IAAI,MAAM,CAAC,QAAQ,CAAC,qBAAqB,CAAC;QAAE,OAAO,IAAI,CAAC;IAExD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAElC,IAAI,SAAS,GAAG,MAAM,CAAC,OAAO,CAC5B,2DAA2D,EAC3D,CAAC,EAAE,EAAE,OAA2B,EAAE,IAAY,EAAE,EAAE;QAChD,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,WAAW,CAAC;YAAE,OAAO,EAAE,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClB,OAAO,GAAG,OAAO,IAAI,EAAE,2BAA2B,IAAI,GAAG,CAAC;IAC5D,CAAC,CACF,CAAC;IAEF,SAAS,GAAG,SAAS,CAAC,OAAO,CAC3B,4CAA4C,EAC5C,CAAC,EAAE,EAAE,IAAY,EAAE,EAAE;QACnB,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,WAAW,CAAC;YAAE,OAAO,EAAE,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClB,OAAO,wBAAwB,IAAI,IAAI,CAAC;IAC1C,CAAC,CACF,CAAC;IAEF,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpC,MAAM,UAAU,GAAG,uCAAuC,qBAAqB,sBAAsB,CAAC;IACtG,MAAM,KAAK,GAAG,CAAC,GAAG,OAAO,CAAC;SACvB,GAAG,CACF,CAAC,IAAI,EAAE,EAAE,CACP,gBAAgB,IAAI,MAAM,qBAAqB,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,IAAI,IAAI,CAC/H;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO,GAAG,UAAU,GAAG,SAAS,KAAK,KAAK,IAAI,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* praetom/webpack — Webpack plugin for praetom.
|
|
3
|
+
*
|
|
4
|
+
* Usage (plain webpack):
|
|
5
|
+
* // webpack.config.js
|
|
6
|
+
* import praetom from "praetom/webpack";
|
|
7
|
+
*
|
|
8
|
+
* export default {
|
|
9
|
+
* plugins: [new praetom.PraetomPlugin()],
|
|
10
|
+
* // ...
|
|
11
|
+
* };
|
|
12
|
+
*
|
|
13
|
+
* Usage (Next.js):
|
|
14
|
+
* // next.config.ts
|
|
15
|
+
* import { PraetomPlugin } from "praetom/webpack";
|
|
16
|
+
*
|
|
17
|
+
* const nextConfig = {
|
|
18
|
+
* webpack(config) {
|
|
19
|
+
* config.plugins.push(new PraetomPlugin());
|
|
20
|
+
* return config;
|
|
21
|
+
* },
|
|
22
|
+
* };
|
|
23
|
+
* export default nextConfig;
|
|
24
|
+
*
|
|
25
|
+
* The plugin fetches the workspace's feature map at build start, then
|
|
26
|
+
* registers a loader rule so every JS/TS module webpack processes runs
|
|
27
|
+
* through the praetom loader. The loader checks each file's path
|
|
28
|
+
* against the feature map and rewrites named exports to call into the
|
|
29
|
+
* SDK's wrap helper.
|
|
30
|
+
*
|
|
31
|
+
* Auth: PRAETOM_INGEST_ID env var at build time, or pass
|
|
32
|
+
* `{ ingestId: "..." }` as constructor option.
|
|
33
|
+
*/
|
|
34
|
+
export interface PraetomPluginOptions {
|
|
35
|
+
ingestId?: string;
|
|
36
|
+
configEndpoint?: string;
|
|
37
|
+
silent?: boolean;
|
|
38
|
+
}
|
|
39
|
+
interface CompilerHooks {
|
|
40
|
+
beforeRun: {
|
|
41
|
+
tapPromise: (name: string, fn: () => Promise<void>) => void;
|
|
42
|
+
};
|
|
43
|
+
watchRun: {
|
|
44
|
+
tapPromise: (name: string, fn: () => Promise<void>) => void;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
interface Compiler {
|
|
48
|
+
options: {
|
|
49
|
+
module?: {
|
|
50
|
+
rules?: unknown[];
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
hooks: CompilerHooks;
|
|
54
|
+
}
|
|
55
|
+
export declare class PraetomPlugin {
|
|
56
|
+
private features;
|
|
57
|
+
private opts;
|
|
58
|
+
private log;
|
|
59
|
+
constructor(opts?: PraetomPluginOptions);
|
|
60
|
+
apply(compiler: Compiler): void;
|
|
61
|
+
private loadFeatureMap;
|
|
62
|
+
}
|
|
63
|
+
export default PraetomPlugin;
|
|
64
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/webpack/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAaH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAKD,UAAU,aAAa;IACrB,SAAS,EAAE;QAAE,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAA;KAAE,CAAC;IAC3E,QAAQ,EAAE;QAAE,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAA;KAAE,CAAC;CAC3E;AAED,UAAU,QAAQ;IAChB,OAAO,EAAE;QACP,MAAM,CAAC,EAAE;YACP,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;SACnB,CAAC;KACH,CAAC;IACF,KAAK,EAAE,aAAa,CAAC;CACtB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,IAAI,CAAuB;IACnC,OAAO,CAAC,GAAG,CAAwB;gBAEvB,IAAI,GAAE,oBAAyB;IAQ3C,KAAK,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;YAiCjB,cAAc;CAyB7B;AAED,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* praetom/webpack — Webpack plugin for praetom.
|
|
3
|
+
*
|
|
4
|
+
* Usage (plain webpack):
|
|
5
|
+
* // webpack.config.js
|
|
6
|
+
* import praetom from "praetom/webpack";
|
|
7
|
+
*
|
|
8
|
+
* export default {
|
|
9
|
+
* plugins: [new praetom.PraetomPlugin()],
|
|
10
|
+
* // ...
|
|
11
|
+
* };
|
|
12
|
+
*
|
|
13
|
+
* Usage (Next.js):
|
|
14
|
+
* // next.config.ts
|
|
15
|
+
* import { PraetomPlugin } from "praetom/webpack";
|
|
16
|
+
*
|
|
17
|
+
* const nextConfig = {
|
|
18
|
+
* webpack(config) {
|
|
19
|
+
* config.plugins.push(new PraetomPlugin());
|
|
20
|
+
* return config;
|
|
21
|
+
* },
|
|
22
|
+
* };
|
|
23
|
+
* export default nextConfig;
|
|
24
|
+
*
|
|
25
|
+
* The plugin fetches the workspace's feature map at build start, then
|
|
26
|
+
* registers a loader rule so every JS/TS module webpack processes runs
|
|
27
|
+
* through the praetom loader. The loader checks each file's path
|
|
28
|
+
* against the feature map and rewrites named exports to call into the
|
|
29
|
+
* SDK's wrap helper.
|
|
30
|
+
*
|
|
31
|
+
* Auth: PRAETOM_INGEST_ID env var at build time, or pass
|
|
32
|
+
* `{ ingestId: "..." }` as constructor option.
|
|
33
|
+
*/
|
|
34
|
+
import { createRequire } from "node:module";
|
|
35
|
+
import { dirname, resolve } from "node:path";
|
|
36
|
+
import { fileURLToPath } from "node:url";
|
|
37
|
+
import { fetchFeatureMap } from "./shared.js";
|
|
38
|
+
const require_ = createRequire(import.meta.url);
|
|
39
|
+
const __filename_ = fileURLToPath(import.meta.url);
|
|
40
|
+
const __dirname_ = dirname(__filename_);
|
|
41
|
+
const DEFAULT_CONFIG_ENDPOINT = "https://praetom.com/api/runtime/config";
|
|
42
|
+
const PLUGIN_NAME = "PraetomPlugin";
|
|
43
|
+
export class PraetomPlugin {
|
|
44
|
+
features = [];
|
|
45
|
+
opts;
|
|
46
|
+
log;
|
|
47
|
+
constructor(opts = {}) {
|
|
48
|
+
this.opts = opts;
|
|
49
|
+
this.log = opts.silent
|
|
50
|
+
? () => { }
|
|
51
|
+
: // eslint-disable-next-line no-console
|
|
52
|
+
(msg) => console.warn(`[praetom] ${msg}`);
|
|
53
|
+
}
|
|
54
|
+
apply(compiler) {
|
|
55
|
+
// Inject the loader as the first rule so it runs before everything else
|
|
56
|
+
// — we want to wrap before TypeScript/SWC strip types or transpile.
|
|
57
|
+
const moduleConfig = (compiler.options.module ??= {});
|
|
58
|
+
const rules = (moduleConfig.rules ??= []);
|
|
59
|
+
const loaderPath = resolve(__dirname_, "./loader.js");
|
|
60
|
+
rules.unshift({
|
|
61
|
+
test: /\.(ts|tsx|js|jsx|mjs|mts)$/,
|
|
62
|
+
exclude: /node_modules/,
|
|
63
|
+
enforce: "pre",
|
|
64
|
+
use: [
|
|
65
|
+
{
|
|
66
|
+
loader: loaderPath,
|
|
67
|
+
options: {
|
|
68
|
+
// Mutated below by the buildStart hook. Loader reads this on
|
|
69
|
+
// every transform call; mutating the same reference is the
|
|
70
|
+
// standard pattern for hot-reloading config from the plugin.
|
|
71
|
+
features: this.features,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
});
|
|
76
|
+
// Kick off the feature-map fetch immediately on apply(). The loader
|
|
77
|
+
// mutates the same `this.features` array reference, so even if a
|
|
78
|
+
// transform fires before the fetch completes, subsequent transforms
|
|
79
|
+
// will see the populated array. In practice the fetch takes <200ms
|
|
80
|
+
// and webpack's first transform fires seconds later, so this is fine
|
|
81
|
+
// for the typical case. Errors throw to surface broken builds early.
|
|
82
|
+
void this.loadFeatureMap();
|
|
83
|
+
}
|
|
84
|
+
async loadFeatureMap() {
|
|
85
|
+
const token = this.opts.ingestId ?? process.env.PRAETOM_INGEST_ID;
|
|
86
|
+
if (!token) {
|
|
87
|
+
this.log("PRAETOM_INGEST_ID not set and no ingestId option passed; build will not auto-wrap any features");
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const endpoint = this.opts.configEndpoint ?? DEFAULT_CONFIG_ENDPOINT;
|
|
91
|
+
try {
|
|
92
|
+
const config = await fetchFeatureMap(endpoint, token);
|
|
93
|
+
// Mutate in place so the loader's options.features reference
|
|
94
|
+
// updates without re-applying the rule.
|
|
95
|
+
this.features.length = 0;
|
|
96
|
+
this.features.push(...config.features);
|
|
97
|
+
this.log(`loaded feature map: ${this.features.length} features in ${config.repo}`);
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
throw new Error(`[praetom] failed to fetch feature map from ${endpoint}: ${e.message}. ` +
|
|
101
|
+
`Set PRAETOM_INGEST_ID to a valid per-repo token or pass { ingestId } to the plugin constructor.`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
export default PraetomPlugin;
|
|
106
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/webpack/index.ts"],"names":[],"mappings":"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"}
|