@merittdev/horus-lens 0.0.3 → 0.1.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 +9 -47
- package/dist/browser.cjs +84 -85
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +2 -4
- package/dist/{chunk-CTBY5XIN.js → chunk-CRV65EEY.js} +40 -2
- package/dist/chunk-CRV65EEY.js.map +1 -0
- package/dist/{chunk-XRONR4GR.js → chunk-UB7YYHI4.js} +13672 -968
- package/dist/chunk-UB7YYHI4.js.map +1 -0
- package/dist/index.cjs +46 -111
- package/dist/index.cjs.map +1 -1
- package/dist/{index.d-BA540Fae.d.ts → index.d-DeLYS02n.d.ts} +13 -0
- package/dist/{index.d-DOCLVJGS.d.cts → index.d-sNoEEgRg.d.cts} +13 -0
- package/dist/index.d.cts +14 -165
- package/dist/index.d.ts +14 -165
- package/dist/index.js +1 -29
- package/dist/lens.min.js +31 -31
- package/dist/lens.min.js.map +1 -1
- package/dist/react.cjs +84 -85
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +2 -4
- package/dist/react.js.map +1 -1
- package/package.json +6 -19
- package/dist/chunk-CTBY5XIN.js.map +0 -1
- package/dist/chunk-DWOH2ENF.js +0 -17613
- package/dist/chunk-DWOH2ENF.js.map +0 -1
- package/dist/chunk-PZ5AY32C.js +0 -10
- package/dist/chunk-PZ5AY32C.js.map +0 -1
- package/dist/chunk-XRONR4GR.js.map +0 -1
- package/dist/dashboard.cjs +0 -20124
- package/dist/dashboard.cjs.map +0 -1
- package/dist/dashboard.css +0 -2456
- package/dist/dashboard.d.cts +0 -791
- package/dist/dashboard.d.ts +0 -791
- package/dist/dashboard.js +0 -2584
- package/dist/dashboard.js.map +0 -1
- package/dist/rrweb-EYUUZIYR.js +0 -30
- package/dist/rrweb-EYUUZIYR.js.map +0 -1
- package/dist/server.cjs +0 -109
- package/dist/server.cjs.map +0 -1
- package/dist/server.d.cts +0 -59
- package/dist/server.d.ts +0 -59
- package/dist/server.js +0 -82
- package/dist/server.js.map +0 -1
package/dist/server.cjs
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/server.ts
|
|
21
|
-
var server_exports = {};
|
|
22
|
-
__export(server_exports, {
|
|
23
|
-
HOSTED_LENS_API_URL: () => HOSTED_LENS_API_URL,
|
|
24
|
-
createLensProjectsRoute: () => createLensProjectsRoute,
|
|
25
|
-
createLensProxy: () => createLensProxy
|
|
26
|
-
});
|
|
27
|
-
module.exports = __toCommonJS(server_exports);
|
|
28
|
-
|
|
29
|
-
// ../dashboard/dist/server.js
|
|
30
|
-
var HOSTED_LENS_API_URL = "https://api-lens.meritt.app";
|
|
31
|
-
function envProjects() {
|
|
32
|
-
const raw = process.env.LENS_PROJECTS;
|
|
33
|
-
if (raw) {
|
|
34
|
-
try {
|
|
35
|
-
const parsed = JSON.parse(raw);
|
|
36
|
-
if (Array.isArray(parsed)) {
|
|
37
|
-
return parsed.filter(
|
|
38
|
-
(p) => !!p && typeof p.name === "string" && typeof p.accessId === "string" && typeof p.secretKey === "string"
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
} catch {
|
|
42
|
-
console.warn("[lens] LENS_PROJECTS is not valid JSON \u2014 ignoring");
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
const accessId = process.env.LENS_ACCESS_ID;
|
|
46
|
-
const secretKey = process.env.LENS_SECRET_KEY;
|
|
47
|
-
if (accessId && secretKey) return [{ name: "default", accessId, secretKey }];
|
|
48
|
-
return [];
|
|
49
|
-
}
|
|
50
|
-
function resolveOptions(options) {
|
|
51
|
-
return {
|
|
52
|
-
apiUrl: (options?.apiUrl ?? process.env.LENS_API_URL ?? HOSTED_LENS_API_URL).replace(/\/+$/, ""),
|
|
53
|
-
projects: options?.projects ?? envProjects(),
|
|
54
|
-
adminToken: options?.adminToken ?? process.env.LENS_ADMIN_TOKEN ?? ""
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
function pickProject(projects, selector) {
|
|
58
|
-
if (projects.length === 0) return null;
|
|
59
|
-
if (selector) {
|
|
60
|
-
const match = projects.find((p) => p.name === selector || p.accessId === selector);
|
|
61
|
-
if (match) return match;
|
|
62
|
-
}
|
|
63
|
-
return projects[0] ?? null;
|
|
64
|
-
}
|
|
65
|
-
function createLensProxy(options) {
|
|
66
|
-
const handler = async (req, ctx) => {
|
|
67
|
-
const { apiUrl, projects, adminToken } = resolveOptions(options);
|
|
68
|
-
const { path } = await ctx.params;
|
|
69
|
-
const search = new URL(req.url).search;
|
|
70
|
-
const target = `${apiUrl}/${path.join("/")}${search}`;
|
|
71
|
-
const isProjectCreate = req.method === "POST" && path.join("/") === "v1/projects";
|
|
72
|
-
const wizardToken = req.headers.get("x-lens-token");
|
|
73
|
-
const project = pickProject(projects, req.headers.get("x-lens-project"));
|
|
74
|
-
const token = isProjectCreate ? adminToken : wizardToken?.startsWith("las_") ? wizardToken : project?.secretKey ?? "";
|
|
75
|
-
const body = req.method === "GET" || req.method === "HEAD" ? void 0 : await req.text();
|
|
76
|
-
const res = await fetch(target, {
|
|
77
|
-
method: req.method,
|
|
78
|
-
headers: {
|
|
79
|
-
authorization: `Bearer ${token}`,
|
|
80
|
-
...body ? { "content-type": req.headers.get("content-type") ?? "application/json" } : {}
|
|
81
|
-
},
|
|
82
|
-
body,
|
|
83
|
-
cache: "no-store"
|
|
84
|
-
});
|
|
85
|
-
const buffer = await res.arrayBuffer();
|
|
86
|
-
return new Response(buffer, {
|
|
87
|
-
status: res.status,
|
|
88
|
-
headers: { "content-type": res.headers.get("content-type") ?? "application/json" }
|
|
89
|
-
});
|
|
90
|
-
};
|
|
91
|
-
return { GET: handler, POST: handler, PUT: handler, PATCH: handler, DELETE: handler };
|
|
92
|
-
}
|
|
93
|
-
function createLensProjectsRoute(options) {
|
|
94
|
-
return {
|
|
95
|
-
GET: () => {
|
|
96
|
-
const { projects } = resolveOptions(options);
|
|
97
|
-
return Response.json({
|
|
98
|
-
projects: projects.map(({ name, accessId }) => ({ name, accessId }))
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
104
|
-
0 && (module.exports = {
|
|
105
|
-
HOSTED_LENS_API_URL,
|
|
106
|
-
createLensProjectsRoute,
|
|
107
|
-
createLensProxy
|
|
108
|
-
});
|
|
109
|
-
//# sourceMappingURL=server.cjs.map
|
package/dist/server.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts","../../dashboard/src/server/proxy.ts"],"sourcesContent":["export * from '@horus-lens/dashboard/server';\n","/**\n * Server-side glue for hosting <LensDashboard> — framework-agnostic (standard\n * Request/Response, so it drops into Next.js App Router route files, Remix\n * resource routes, etc.).\n *\n * This is the ONLY part of the package that reads environment variables, and\n * it only ever executes on the host's server:\n *\n * LENS_PROJECTS JSON array: [{\"name\",\"accessId\",\"secretKey\"}, …]\n * LENS_ACCESS_ID /\n * LENS_SECRET_KEY legacy single-project fallback\n * LENS_ADMIN_TOKEN optional — enables project creation from the wizard\n * LENS_API_URL optional override (self-hosting / local dev)\n *\n * Usage (Next.js):\n * // app/api/lens/[...path]/route.ts\n * import { createLensProxy } from '@merittdev/horus-lens/server'\n * export const { GET, POST, PUT, PATCH, DELETE } = createLensProxy()\n *\n * // app/api/lens-projects/route.ts\n * import { createLensProjectsRoute } from '@merittdev/horus-lens/server'\n * export const { GET } = createLensProjectsRoute()\n */\n\n// Runs under Node on the host's server; typed locally to keep @types/node out\n// of this browser-focused package.\ndeclare const process: { env: Record<string, string | undefined> };\n\nexport const HOSTED_LENS_API_URL = 'https://api-lens.meritt.app';\n\nexport interface LensProjectEntry {\n name: string;\n accessId: string;\n secretKey: string;\n}\n\nexport interface LensServerOptions {\n /** Lens API base. Default: env LENS_API_URL, else the hosted API. */\n apiUrl?: string;\n /** Project registry. Default: env LENS_PROJECTS (JSON), else the legacy pair. */\n projects?: LensProjectEntry[];\n /** Admin token for POST /v1/projects. Default: env LENS_ADMIN_TOKEN. */\n adminToken?: string;\n}\n\nfunction envProjects(): LensProjectEntry[] {\n const raw = process.env.LENS_PROJECTS;\n if (raw) {\n try {\n const parsed: unknown = JSON.parse(raw);\n if (Array.isArray(parsed)) {\n return parsed.filter(\n (p): p is LensProjectEntry =>\n !!p &&\n typeof (p as LensProjectEntry).name === 'string' &&\n typeof (p as LensProjectEntry).accessId === 'string' &&\n typeof (p as LensProjectEntry).secretKey === 'string',\n );\n }\n } catch {\n console.warn('[lens] LENS_PROJECTS is not valid JSON — ignoring');\n }\n }\n const accessId = process.env.LENS_ACCESS_ID;\n const secretKey = process.env.LENS_SECRET_KEY;\n if (accessId && secretKey) return [{ name: 'default', accessId, secretKey }];\n return [];\n}\n\nfunction resolveOptions(options?: LensServerOptions) {\n return {\n apiUrl: (options?.apiUrl ?? process.env.LENS_API_URL ?? HOSTED_LENS_API_URL).replace(/\\/+$/, ''),\n projects: options?.projects ?? envProjects(),\n adminToken: options?.adminToken ?? process.env.LENS_ADMIN_TOKEN ?? '',\n };\n}\n\nfunction pickProject(projects: LensProjectEntry[], selector: string | null): LensProjectEntry | null {\n if (projects.length === 0) return null;\n if (selector) {\n const match = projects.find((p) => p.name === selector || p.accessId === selector);\n if (match) return match;\n }\n return projects[0] ?? null;\n}\n\n/** Next.js App Router passes ctx.params as a Promise (15+) or plain object. */\ntype RouteContext = { params: { path: string[] } | Promise<{ path: string[] }> };\ntype ProxyHandler = (req: Request, ctx: RouteContext) => Promise<Response>;\n\n/**\n * Authenticated pass-through to the Lens API. Credentials attach HERE, on the\n * server: the browser only ever names a project via `x-lens-project`. During\n * first-run provisioning the wizard forwards its just-minted secret via\n * `x-lens-token`, which wins over the registry.\n */\nexport function createLensProxy(options?: LensServerOptions): Record<\n 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n ProxyHandler\n> {\n const handler: ProxyHandler = async (req, ctx) => {\n const { apiUrl, projects, adminToken } = resolveOptions(options);\n const { path } = await ctx.params;\n const search = new URL(req.url).search;\n const target = `${apiUrl}/${path.join('/')}${search}`;\n\n const isProjectCreate = req.method === 'POST' && path.join('/') === 'v1/projects';\n const wizardToken = req.headers.get('x-lens-token');\n const project = pickProject(projects, req.headers.get('x-lens-project'));\n\n const token = isProjectCreate\n ? adminToken\n : wizardToken?.startsWith('las_')\n ? wizardToken\n : (project?.secretKey ?? '');\n\n const body = req.method === 'GET' || req.method === 'HEAD' ? undefined : await req.text();\n\n const res = await fetch(target, {\n method: req.method,\n headers: {\n authorization: `Bearer ${token}`,\n ...(body ? { 'content-type': req.headers.get('content-type') ?? 'application/json' } : {}),\n },\n body,\n cache: 'no-store',\n });\n\n const buffer = await res.arrayBuffer();\n return new Response(buffer, {\n status: res.status,\n headers: { 'content-type': res.headers.get('content-type') ?? 'application/json' },\n });\n };\n\n return { GET: handler, POST: handler, PUT: handler, PATCH: handler, DELETE: handler };\n}\n\n/** Names + access ids for the project switcher — never the secrets. */\nexport function createLensProjectsRoute(options?: LensServerOptions): { GET: () => Response } {\n return {\n GET: () => {\n const { projects } = resolveOptions(options);\n return Response.json({\n projects: projects.map(({ name, accessId }) => ({ name, accessId })),\n });\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC4BO,IAAM,sBAAsB;AAiBnC,SAAS,cAAkC;AACzC,QAAM,MAAM,QAAQ,IAAI;AACxB,MAAI,KAAK;AACP,QAAI;AACF,YAAM,SAAkB,KAAK,MAAM,GAAG;AACtC,UAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,eAAO,OAAO;UACZ,CAAC,MACC,CAAC,CAAC,KACF,OAAQ,EAAuB,SAAS,YACxC,OAAQ,EAAuB,aAAa,YAC5C,OAAQ,EAAuB,cAAc;QACjD;MACF;IACF,QAAQ;AACN,cAAQ,KAAK,wDAAmD;IAClE;EACF;AACA,QAAM,WAAW,QAAQ,IAAI;AAC7B,QAAM,YAAY,QAAQ,IAAI;AAC9B,MAAI,YAAY,UAAW,QAAO,CAAC,EAAE,MAAM,WAAW,UAAU,UAAU,CAAC;AAC3E,SAAO,CAAC;AACV;AAEA,SAAS,eAAe,SAA6B;AACnD,SAAO;IACL,SAAS,SAAS,UAAU,QAAQ,IAAI,gBAAgB,qBAAqB,QAAQ,QAAQ,EAAE;IAC/F,UAAU,SAAS,YAAY,YAAY;IAC3C,YAAY,SAAS,cAAc,QAAQ,IAAI,oBAAoB;EACrE;AACF;AAEA,SAAS,YAAY,UAA8B,UAAkD;AACnG,MAAI,SAAS,WAAW,EAAG,QAAO;AAClC,MAAI,UAAU;AACZ,UAAM,QAAQ,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,aAAa,QAAQ;AACjF,QAAI,MAAO,QAAO;EACpB;AACA,SAAO,SAAS,CAAC,KAAK;AACxB;AAYO,SAAS,gBAAgB,SAG9B;AACA,QAAM,UAAwB,OAAO,KAAK,QAAQ;AAChD,UAAM,EAAE,QAAQ,UAAU,WAAW,IAAI,eAAe,OAAO;AAC/D,UAAM,EAAE,KAAK,IAAI,MAAM,IAAI;AAC3B,UAAM,SAAS,IAAI,IAAI,IAAI,GAAG,EAAE;AAChC,UAAM,SAAS,GAAG,MAAM,IAAI,KAAK,KAAK,GAAG,CAAC,GAAG,MAAM;AAEnD,UAAM,kBAAkB,IAAI,WAAW,UAAU,KAAK,KAAK,GAAG,MAAM;AACpE,UAAM,cAAc,IAAI,QAAQ,IAAI,cAAc;AAClD,UAAM,UAAU,YAAY,UAAU,IAAI,QAAQ,IAAI,gBAAgB,CAAC;AAEvE,UAAM,QAAQ,kBACV,aACA,aAAa,WAAW,MAAM,IAC5B,cACC,SAAS,aAAa;AAE7B,UAAM,OAAO,IAAI,WAAW,SAAS,IAAI,WAAW,SAAS,SAAY,MAAM,IAAI,KAAK;AAExF,UAAM,MAAM,MAAM,MAAM,QAAQ;MAC9B,QAAQ,IAAI;MACZ,SAAS;QACP,eAAe,UAAU,KAAK;QAC9B,GAAI,OAAO,EAAE,gBAAgB,IAAI,QAAQ,IAAI,cAAc,KAAK,mBAAmB,IAAI,CAAC;MAC1F;MACA;MACA,OAAO;IACT,CAAC;AAED,UAAM,SAAS,MAAM,IAAI,YAAY;AACrC,WAAO,IAAI,SAAS,QAAQ;MAC1B,QAAQ,IAAI;MACZ,SAAS,EAAE,gBAAgB,IAAI,QAAQ,IAAI,cAAc,KAAK,mBAAmB;IACnF,CAAC;EACH;AAEA,SAAO,EAAE,KAAK,SAAS,MAAM,SAAS,KAAK,SAAS,OAAO,SAAS,QAAQ,QAAQ;AACtF;AAGO,SAAS,wBAAwB,SAAsD;AAC5F,SAAO;IACL,KAAK,MAAM;AACT,YAAM,EAAE,SAAS,IAAI,eAAe,OAAO;AAC3C,aAAO,SAAS,KAAK;QACnB,UAAU,SAAS,IAAI,CAAC,EAAE,MAAM,SAAS,OAAO,EAAE,MAAM,SAAS,EAAE;MACrE,CAAC;IACH;EACF;AACF;","names":[]}
|
package/dist/server.d.cts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Server-side glue for hosting <LensDashboard> — framework-agnostic (standard
|
|
3
|
-
* Request/Response, so it drops into Next.js App Router route files, Remix
|
|
4
|
-
* resource routes, etc.).
|
|
5
|
-
*
|
|
6
|
-
* This is the ONLY part of the package that reads environment variables, and
|
|
7
|
-
* it only ever executes on the host's server:
|
|
8
|
-
*
|
|
9
|
-
* LENS_PROJECTS JSON array: [{"name","accessId","secretKey"}, …]
|
|
10
|
-
* LENS_ACCESS_ID /
|
|
11
|
-
* LENS_SECRET_KEY legacy single-project fallback
|
|
12
|
-
* LENS_ADMIN_TOKEN optional — enables project creation from the wizard
|
|
13
|
-
* LENS_API_URL optional override (self-hosting / local dev)
|
|
14
|
-
*
|
|
15
|
-
* Usage (Next.js):
|
|
16
|
-
* // app/api/lens/[...path]/route.ts
|
|
17
|
-
* import { createLensProxy } from '@merittdev/horus-lens/server'
|
|
18
|
-
* export const { GET, POST, PUT, PATCH, DELETE } = createLensProxy()
|
|
19
|
-
*
|
|
20
|
-
* // app/api/lens-projects/route.ts
|
|
21
|
-
* import { createLensProjectsRoute } from '@merittdev/horus-lens/server'
|
|
22
|
-
* export const { GET } = createLensProjectsRoute()
|
|
23
|
-
*/
|
|
24
|
-
declare const HOSTED_LENS_API_URL = "https://api-lens.meritt.app";
|
|
25
|
-
interface LensProjectEntry {
|
|
26
|
-
name: string;
|
|
27
|
-
accessId: string;
|
|
28
|
-
secretKey: string;
|
|
29
|
-
}
|
|
30
|
-
interface LensServerOptions {
|
|
31
|
-
/** Lens API base. Default: env LENS_API_URL, else the hosted API. */
|
|
32
|
-
apiUrl?: string;
|
|
33
|
-
/** Project registry. Default: env LENS_PROJECTS (JSON), else the legacy pair. */
|
|
34
|
-
projects?: LensProjectEntry[];
|
|
35
|
-
/** Admin token for POST /v1/projects. Default: env LENS_ADMIN_TOKEN. */
|
|
36
|
-
adminToken?: string;
|
|
37
|
-
}
|
|
38
|
-
/** Next.js App Router passes ctx.params as a Promise (15+) or plain object. */
|
|
39
|
-
type RouteContext = {
|
|
40
|
-
params: {
|
|
41
|
-
path: string[];
|
|
42
|
-
} | Promise<{
|
|
43
|
-
path: string[];
|
|
44
|
-
}>;
|
|
45
|
-
};
|
|
46
|
-
type ProxyHandler = (req: Request, ctx: RouteContext) => Promise<Response>;
|
|
47
|
-
/**
|
|
48
|
-
* Authenticated pass-through to the Lens API. Credentials attach HERE, on the
|
|
49
|
-
* server: the browser only ever names a project via `x-lens-project`. During
|
|
50
|
-
* first-run provisioning the wizard forwards its just-minted secret via
|
|
51
|
-
* `x-lens-token`, which wins over the registry.
|
|
52
|
-
*/
|
|
53
|
-
declare function createLensProxy(options?: LensServerOptions): Record<'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE', ProxyHandler>;
|
|
54
|
-
/** Names + access ids for the project switcher — never the secrets. */
|
|
55
|
-
declare function createLensProjectsRoute(options?: LensServerOptions): {
|
|
56
|
-
GET: () => Response;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
export { HOSTED_LENS_API_URL, type LensProjectEntry, type LensServerOptions, createLensProjectsRoute, createLensProxy };
|
package/dist/server.d.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Server-side glue for hosting <LensDashboard> — framework-agnostic (standard
|
|
3
|
-
* Request/Response, so it drops into Next.js App Router route files, Remix
|
|
4
|
-
* resource routes, etc.).
|
|
5
|
-
*
|
|
6
|
-
* This is the ONLY part of the package that reads environment variables, and
|
|
7
|
-
* it only ever executes on the host's server:
|
|
8
|
-
*
|
|
9
|
-
* LENS_PROJECTS JSON array: [{"name","accessId","secretKey"}, …]
|
|
10
|
-
* LENS_ACCESS_ID /
|
|
11
|
-
* LENS_SECRET_KEY legacy single-project fallback
|
|
12
|
-
* LENS_ADMIN_TOKEN optional — enables project creation from the wizard
|
|
13
|
-
* LENS_API_URL optional override (self-hosting / local dev)
|
|
14
|
-
*
|
|
15
|
-
* Usage (Next.js):
|
|
16
|
-
* // app/api/lens/[...path]/route.ts
|
|
17
|
-
* import { createLensProxy } from '@merittdev/horus-lens/server'
|
|
18
|
-
* export const { GET, POST, PUT, PATCH, DELETE } = createLensProxy()
|
|
19
|
-
*
|
|
20
|
-
* // app/api/lens-projects/route.ts
|
|
21
|
-
* import { createLensProjectsRoute } from '@merittdev/horus-lens/server'
|
|
22
|
-
* export const { GET } = createLensProjectsRoute()
|
|
23
|
-
*/
|
|
24
|
-
declare const HOSTED_LENS_API_URL = "https://api-lens.meritt.app";
|
|
25
|
-
interface LensProjectEntry {
|
|
26
|
-
name: string;
|
|
27
|
-
accessId: string;
|
|
28
|
-
secretKey: string;
|
|
29
|
-
}
|
|
30
|
-
interface LensServerOptions {
|
|
31
|
-
/** Lens API base. Default: env LENS_API_URL, else the hosted API. */
|
|
32
|
-
apiUrl?: string;
|
|
33
|
-
/** Project registry. Default: env LENS_PROJECTS (JSON), else the legacy pair. */
|
|
34
|
-
projects?: LensProjectEntry[];
|
|
35
|
-
/** Admin token for POST /v1/projects. Default: env LENS_ADMIN_TOKEN. */
|
|
36
|
-
adminToken?: string;
|
|
37
|
-
}
|
|
38
|
-
/** Next.js App Router passes ctx.params as a Promise (15+) or plain object. */
|
|
39
|
-
type RouteContext = {
|
|
40
|
-
params: {
|
|
41
|
-
path: string[];
|
|
42
|
-
} | Promise<{
|
|
43
|
-
path: string[];
|
|
44
|
-
}>;
|
|
45
|
-
};
|
|
46
|
-
type ProxyHandler = (req: Request, ctx: RouteContext) => Promise<Response>;
|
|
47
|
-
/**
|
|
48
|
-
* Authenticated pass-through to the Lens API. Credentials attach HERE, on the
|
|
49
|
-
* server: the browser only ever names a project via `x-lens-project`. During
|
|
50
|
-
* first-run provisioning the wizard forwards its just-minted secret via
|
|
51
|
-
* `x-lens-token`, which wins over the registry.
|
|
52
|
-
*/
|
|
53
|
-
declare function createLensProxy(options?: LensServerOptions): Record<'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE', ProxyHandler>;
|
|
54
|
-
/** Names + access ids for the project switcher — never the secrets. */
|
|
55
|
-
declare function createLensProjectsRoute(options?: LensServerOptions): {
|
|
56
|
-
GET: () => Response;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
export { HOSTED_LENS_API_URL, type LensProjectEntry, type LensServerOptions, createLensProjectsRoute, createLensProxy };
|
package/dist/server.js
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import "./chunk-PZ5AY32C.js";
|
|
2
|
-
|
|
3
|
-
// ../dashboard/dist/server.js
|
|
4
|
-
var HOSTED_LENS_API_URL = "https://api-lens.meritt.app";
|
|
5
|
-
function envProjects() {
|
|
6
|
-
const raw = process.env.LENS_PROJECTS;
|
|
7
|
-
if (raw) {
|
|
8
|
-
try {
|
|
9
|
-
const parsed = JSON.parse(raw);
|
|
10
|
-
if (Array.isArray(parsed)) {
|
|
11
|
-
return parsed.filter(
|
|
12
|
-
(p) => !!p && typeof p.name === "string" && typeof p.accessId === "string" && typeof p.secretKey === "string"
|
|
13
|
-
);
|
|
14
|
-
}
|
|
15
|
-
} catch {
|
|
16
|
-
console.warn("[lens] LENS_PROJECTS is not valid JSON \u2014 ignoring");
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
const accessId = process.env.LENS_ACCESS_ID;
|
|
20
|
-
const secretKey = process.env.LENS_SECRET_KEY;
|
|
21
|
-
if (accessId && secretKey) return [{ name: "default", accessId, secretKey }];
|
|
22
|
-
return [];
|
|
23
|
-
}
|
|
24
|
-
function resolveOptions(options) {
|
|
25
|
-
return {
|
|
26
|
-
apiUrl: (options?.apiUrl ?? process.env.LENS_API_URL ?? HOSTED_LENS_API_URL).replace(/\/+$/, ""),
|
|
27
|
-
projects: options?.projects ?? envProjects(),
|
|
28
|
-
adminToken: options?.adminToken ?? process.env.LENS_ADMIN_TOKEN ?? ""
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
function pickProject(projects, selector) {
|
|
32
|
-
if (projects.length === 0) return null;
|
|
33
|
-
if (selector) {
|
|
34
|
-
const match = projects.find((p) => p.name === selector || p.accessId === selector);
|
|
35
|
-
if (match) return match;
|
|
36
|
-
}
|
|
37
|
-
return projects[0] ?? null;
|
|
38
|
-
}
|
|
39
|
-
function createLensProxy(options) {
|
|
40
|
-
const handler = async (req, ctx) => {
|
|
41
|
-
const { apiUrl, projects, adminToken } = resolveOptions(options);
|
|
42
|
-
const { path } = await ctx.params;
|
|
43
|
-
const search = new URL(req.url).search;
|
|
44
|
-
const target = `${apiUrl}/${path.join("/")}${search}`;
|
|
45
|
-
const isProjectCreate = req.method === "POST" && path.join("/") === "v1/projects";
|
|
46
|
-
const wizardToken = req.headers.get("x-lens-token");
|
|
47
|
-
const project = pickProject(projects, req.headers.get("x-lens-project"));
|
|
48
|
-
const token = isProjectCreate ? adminToken : wizardToken?.startsWith("las_") ? wizardToken : project?.secretKey ?? "";
|
|
49
|
-
const body = req.method === "GET" || req.method === "HEAD" ? void 0 : await req.text();
|
|
50
|
-
const res = await fetch(target, {
|
|
51
|
-
method: req.method,
|
|
52
|
-
headers: {
|
|
53
|
-
authorization: `Bearer ${token}`,
|
|
54
|
-
...body ? { "content-type": req.headers.get("content-type") ?? "application/json" } : {}
|
|
55
|
-
},
|
|
56
|
-
body,
|
|
57
|
-
cache: "no-store"
|
|
58
|
-
});
|
|
59
|
-
const buffer = await res.arrayBuffer();
|
|
60
|
-
return new Response(buffer, {
|
|
61
|
-
status: res.status,
|
|
62
|
-
headers: { "content-type": res.headers.get("content-type") ?? "application/json" }
|
|
63
|
-
});
|
|
64
|
-
};
|
|
65
|
-
return { GET: handler, POST: handler, PUT: handler, PATCH: handler, DELETE: handler };
|
|
66
|
-
}
|
|
67
|
-
function createLensProjectsRoute(options) {
|
|
68
|
-
return {
|
|
69
|
-
GET: () => {
|
|
70
|
-
const { projects } = resolveOptions(options);
|
|
71
|
-
return Response.json({
|
|
72
|
-
projects: projects.map(({ name, accessId }) => ({ name, accessId }))
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
export {
|
|
78
|
-
HOSTED_LENS_API_URL,
|
|
79
|
-
createLensProjectsRoute,
|
|
80
|
-
createLensProxy
|
|
81
|
-
};
|
|
82
|
-
//# sourceMappingURL=server.js.map
|
package/dist/server.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../dashboard/src/server/proxy.ts"],"sourcesContent":["/**\n * Server-side glue for hosting <LensDashboard> — framework-agnostic (standard\n * Request/Response, so it drops into Next.js App Router route files, Remix\n * resource routes, etc.).\n *\n * This is the ONLY part of the package that reads environment variables, and\n * it only ever executes on the host's server:\n *\n * LENS_PROJECTS JSON array: [{\"name\",\"accessId\",\"secretKey\"}, …]\n * LENS_ACCESS_ID /\n * LENS_SECRET_KEY legacy single-project fallback\n * LENS_ADMIN_TOKEN optional — enables project creation from the wizard\n * LENS_API_URL optional override (self-hosting / local dev)\n *\n * Usage (Next.js):\n * // app/api/lens/[...path]/route.ts\n * import { createLensProxy } from '@merittdev/horus-lens/server'\n * export const { GET, POST, PUT, PATCH, DELETE } = createLensProxy()\n *\n * // app/api/lens-projects/route.ts\n * import { createLensProjectsRoute } from '@merittdev/horus-lens/server'\n * export const { GET } = createLensProjectsRoute()\n */\n\n// Runs under Node on the host's server; typed locally to keep @types/node out\n// of this browser-focused package.\ndeclare const process: { env: Record<string, string | undefined> };\n\nexport const HOSTED_LENS_API_URL = 'https://api-lens.meritt.app';\n\nexport interface LensProjectEntry {\n name: string;\n accessId: string;\n secretKey: string;\n}\n\nexport interface LensServerOptions {\n /** Lens API base. Default: env LENS_API_URL, else the hosted API. */\n apiUrl?: string;\n /** Project registry. Default: env LENS_PROJECTS (JSON), else the legacy pair. */\n projects?: LensProjectEntry[];\n /** Admin token for POST /v1/projects. Default: env LENS_ADMIN_TOKEN. */\n adminToken?: string;\n}\n\nfunction envProjects(): LensProjectEntry[] {\n const raw = process.env.LENS_PROJECTS;\n if (raw) {\n try {\n const parsed: unknown = JSON.parse(raw);\n if (Array.isArray(parsed)) {\n return parsed.filter(\n (p): p is LensProjectEntry =>\n !!p &&\n typeof (p as LensProjectEntry).name === 'string' &&\n typeof (p as LensProjectEntry).accessId === 'string' &&\n typeof (p as LensProjectEntry).secretKey === 'string',\n );\n }\n } catch {\n console.warn('[lens] LENS_PROJECTS is not valid JSON — ignoring');\n }\n }\n const accessId = process.env.LENS_ACCESS_ID;\n const secretKey = process.env.LENS_SECRET_KEY;\n if (accessId && secretKey) return [{ name: 'default', accessId, secretKey }];\n return [];\n}\n\nfunction resolveOptions(options?: LensServerOptions) {\n return {\n apiUrl: (options?.apiUrl ?? process.env.LENS_API_URL ?? HOSTED_LENS_API_URL).replace(/\\/+$/, ''),\n projects: options?.projects ?? envProjects(),\n adminToken: options?.adminToken ?? process.env.LENS_ADMIN_TOKEN ?? '',\n };\n}\n\nfunction pickProject(projects: LensProjectEntry[], selector: string | null): LensProjectEntry | null {\n if (projects.length === 0) return null;\n if (selector) {\n const match = projects.find((p) => p.name === selector || p.accessId === selector);\n if (match) return match;\n }\n return projects[0] ?? null;\n}\n\n/** Next.js App Router passes ctx.params as a Promise (15+) or plain object. */\ntype RouteContext = { params: { path: string[] } | Promise<{ path: string[] }> };\ntype ProxyHandler = (req: Request, ctx: RouteContext) => Promise<Response>;\n\n/**\n * Authenticated pass-through to the Lens API. Credentials attach HERE, on the\n * server: the browser only ever names a project via `x-lens-project`. During\n * first-run provisioning the wizard forwards its just-minted secret via\n * `x-lens-token`, which wins over the registry.\n */\nexport function createLensProxy(options?: LensServerOptions): Record<\n 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n ProxyHandler\n> {\n const handler: ProxyHandler = async (req, ctx) => {\n const { apiUrl, projects, adminToken } = resolveOptions(options);\n const { path } = await ctx.params;\n const search = new URL(req.url).search;\n const target = `${apiUrl}/${path.join('/')}${search}`;\n\n const isProjectCreate = req.method === 'POST' && path.join('/') === 'v1/projects';\n const wizardToken = req.headers.get('x-lens-token');\n const project = pickProject(projects, req.headers.get('x-lens-project'));\n\n const token = isProjectCreate\n ? adminToken\n : wizardToken?.startsWith('las_')\n ? wizardToken\n : (project?.secretKey ?? '');\n\n const body = req.method === 'GET' || req.method === 'HEAD' ? undefined : await req.text();\n\n const res = await fetch(target, {\n method: req.method,\n headers: {\n authorization: `Bearer ${token}`,\n ...(body ? { 'content-type': req.headers.get('content-type') ?? 'application/json' } : {}),\n },\n body,\n cache: 'no-store',\n });\n\n const buffer = await res.arrayBuffer();\n return new Response(buffer, {\n status: res.status,\n headers: { 'content-type': res.headers.get('content-type') ?? 'application/json' },\n });\n };\n\n return { GET: handler, POST: handler, PUT: handler, PATCH: handler, DELETE: handler };\n}\n\n/** Names + access ids for the project switcher — never the secrets. */\nexport function createLensProjectsRoute(options?: LensServerOptions): { GET: () => Response } {\n return {\n GET: () => {\n const { projects } = resolveOptions(options);\n return Response.json({\n projects: projects.map(({ name, accessId }) => ({ name, accessId })),\n });\n },\n };\n}\n"],"mappings":";;;AA4BO,IAAM,sBAAsB;AAiBnC,SAAS,cAAkC;AACzC,QAAM,MAAM,QAAQ,IAAI;AACxB,MAAI,KAAK;AACP,QAAI;AACF,YAAM,SAAkB,KAAK,MAAM,GAAG;AACtC,UAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,eAAO,OAAO;UACZ,CAAC,MACC,CAAC,CAAC,KACF,OAAQ,EAAuB,SAAS,YACxC,OAAQ,EAAuB,aAAa,YAC5C,OAAQ,EAAuB,cAAc;QACjD;MACF;IACF,QAAQ;AACN,cAAQ,KAAK,wDAAmD;IAClE;EACF;AACA,QAAM,WAAW,QAAQ,IAAI;AAC7B,QAAM,YAAY,QAAQ,IAAI;AAC9B,MAAI,YAAY,UAAW,QAAO,CAAC,EAAE,MAAM,WAAW,UAAU,UAAU,CAAC;AAC3E,SAAO,CAAC;AACV;AAEA,SAAS,eAAe,SAA6B;AACnD,SAAO;IACL,SAAS,SAAS,UAAU,QAAQ,IAAI,gBAAgB,qBAAqB,QAAQ,QAAQ,EAAE;IAC/F,UAAU,SAAS,YAAY,YAAY;IAC3C,YAAY,SAAS,cAAc,QAAQ,IAAI,oBAAoB;EACrE;AACF;AAEA,SAAS,YAAY,UAA8B,UAAkD;AACnG,MAAI,SAAS,WAAW,EAAG,QAAO;AAClC,MAAI,UAAU;AACZ,UAAM,QAAQ,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,aAAa,QAAQ;AACjF,QAAI,MAAO,QAAO;EACpB;AACA,SAAO,SAAS,CAAC,KAAK;AACxB;AAYO,SAAS,gBAAgB,SAG9B;AACA,QAAM,UAAwB,OAAO,KAAK,QAAQ;AAChD,UAAM,EAAE,QAAQ,UAAU,WAAW,IAAI,eAAe,OAAO;AAC/D,UAAM,EAAE,KAAK,IAAI,MAAM,IAAI;AAC3B,UAAM,SAAS,IAAI,IAAI,IAAI,GAAG,EAAE;AAChC,UAAM,SAAS,GAAG,MAAM,IAAI,KAAK,KAAK,GAAG,CAAC,GAAG,MAAM;AAEnD,UAAM,kBAAkB,IAAI,WAAW,UAAU,KAAK,KAAK,GAAG,MAAM;AACpE,UAAM,cAAc,IAAI,QAAQ,IAAI,cAAc;AAClD,UAAM,UAAU,YAAY,UAAU,IAAI,QAAQ,IAAI,gBAAgB,CAAC;AAEvE,UAAM,QAAQ,kBACV,aACA,aAAa,WAAW,MAAM,IAC5B,cACC,SAAS,aAAa;AAE7B,UAAM,OAAO,IAAI,WAAW,SAAS,IAAI,WAAW,SAAS,SAAY,MAAM,IAAI,KAAK;AAExF,UAAM,MAAM,MAAM,MAAM,QAAQ;MAC9B,QAAQ,IAAI;MACZ,SAAS;QACP,eAAe,UAAU,KAAK;QAC9B,GAAI,OAAO,EAAE,gBAAgB,IAAI,QAAQ,IAAI,cAAc,KAAK,mBAAmB,IAAI,CAAC;MAC1F;MACA;MACA,OAAO;IACT,CAAC;AAED,UAAM,SAAS,MAAM,IAAI,YAAY;AACrC,WAAO,IAAI,SAAS,QAAQ;MAC1B,QAAQ,IAAI;MACZ,SAAS,EAAE,gBAAgB,IAAI,QAAQ,IAAI,cAAc,KAAK,mBAAmB;IACnF,CAAC;EACH;AAEA,SAAO,EAAE,KAAK,SAAS,MAAM,SAAS,KAAK,SAAS,OAAO,SAAS,QAAQ,QAAQ;AACtF;AAGO,SAAS,wBAAwB,SAAsD;AAC5F,SAAO;IACL,KAAK,MAAM;AACT,YAAM,EAAE,SAAS,IAAI,eAAe,OAAO;AAC3C,aAAO,SAAS,KAAK;QACnB,UAAU,SAAS,IAAI,CAAC,EAAE,MAAM,SAAS,OAAO,EAAE,MAAM,SAAS,EAAE;MACrE,CAAC;IACH;EACF;AACF;","names":[]}
|