@rc-tool/unified-auth-hosted-service 0.2.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.
Files changed (130) hide show
  1. package/README.md +5 -0
  2. package/dist/cli/env.d.ts +40 -0
  3. package/dist/cli/env.d.ts.map +1 -0
  4. package/dist/cli/env.js +350 -0
  5. package/dist/cli/env.js.map +1 -0
  6. package/dist/cli/index.d.ts +4 -0
  7. package/dist/cli/index.d.ts.map +1 -0
  8. package/dist/cli/index.js +145 -0
  9. package/dist/cli/index.js.map +1 -0
  10. package/dist/cli.d.ts +3 -0
  11. package/dist/cli.d.ts.map +1 -0
  12. package/dist/cli.js +4 -0
  13. package/dist/cli.js.map +1 -0
  14. package/dist/hosted-service/applications.d.ts +8 -0
  15. package/dist/hosted-service/applications.d.ts.map +1 -0
  16. package/dist/hosted-service/applications.js +33 -0
  17. package/dist/hosted-service/applications.js.map +1 -0
  18. package/dist/hosted-service/constants.d.ts +6 -0
  19. package/dist/hosted-service/constants.d.ts.map +1 -0
  20. package/dist/hosted-service/constants.js +6 -0
  21. package/dist/hosted-service/constants.js.map +1 -0
  22. package/dist/hosted-service/cookies.d.ts +17 -0
  23. package/dist/hosted-service/cookies.d.ts.map +1 -0
  24. package/dist/hosted-service/cookies.js +56 -0
  25. package/dist/hosted-service/cookies.js.map +1 -0
  26. package/dist/hosted-service/crypto.d.ts +3 -0
  27. package/dist/hosted-service/crypto.d.ts.map +1 -0
  28. package/dist/hosted-service/crypto.js +39 -0
  29. package/dist/hosted-service/crypto.js.map +1 -0
  30. package/dist/hosted-service/http.d.ts +4 -0
  31. package/dist/hosted-service/http.d.ts.map +1 -0
  32. package/dist/hosted-service/http.js +27 -0
  33. package/dist/hosted-service/http.js.map +1 -0
  34. package/dist/hosted-service/login-page/components.d.ts +7 -0
  35. package/dist/hosted-service/login-page/components.d.ts.map +1 -0
  36. package/dist/hosted-service/login-page/components.js +40 -0
  37. package/dist/hosted-service/login-page/components.js.map +1 -0
  38. package/dist/hosted-service/login-page/document.d.ts +5 -0
  39. package/dist/hosted-service/login-page/document.d.ts.map +1 -0
  40. package/dist/hosted-service/login-page/document.js +19 -0
  41. package/dist/hosted-service/login-page/document.js.map +1 -0
  42. package/dist/hosted-service/login-page/escape.d.ts +2 -0
  43. package/dist/hosted-service/login-page/escape.d.ts.map +1 -0
  44. package/dist/hosted-service/login-page/escape.js +9 -0
  45. package/dist/hosted-service/login-page/escape.js.map +1 -0
  46. package/dist/hosted-service/login-page/icons.d.ts +5 -0
  47. package/dist/hosted-service/login-page/icons.d.ts.map +1 -0
  48. package/dist/hosted-service/login-page/icons.js +20 -0
  49. package/dist/hosted-service/login-page/icons.js.map +1 -0
  50. package/dist/hosted-service/login-page/index.d.ts +3 -0
  51. package/dist/hosted-service/login-page/index.d.ts.map +1 -0
  52. package/dist/hosted-service/login-page/index.js +23 -0
  53. package/dist/hosted-service/login-page/index.js.map +1 -0
  54. package/dist/hosted-service/login-page/links.d.ts +3 -0
  55. package/dist/hosted-service/login-page/links.d.ts.map +1 -0
  56. package/dist/hosted-service/login-page/links.js +50 -0
  57. package/dist/hosted-service/login-page/links.js.map +1 -0
  58. package/dist/hosted-service/login-page/styles.d.ts +2 -0
  59. package/dist/hosted-service/login-page/styles.d.ts.map +1 -0
  60. package/dist/hosted-service/login-page/styles.js +35 -0
  61. package/dist/hosted-service/login-page/styles.js.map +1 -0
  62. package/dist/hosted-service/login-page/types.d.ts +26 -0
  63. package/dist/hosted-service/login-page/types.d.ts.map +1 -0
  64. package/dist/hosted-service/login-page/types.js +2 -0
  65. package/dist/hosted-service/login-page/types.js.map +1 -0
  66. package/dist/hosted-service/oauth.d.ts +11 -0
  67. package/dist/hosted-service/oauth.d.ts.map +1 -0
  68. package/dist/hosted-service/oauth.js +37 -0
  69. package/dist/hosted-service/oauth.js.map +1 -0
  70. package/dist/hosted-service/providers/feishu.d.ts +4 -0
  71. package/dist/hosted-service/providers/feishu.d.ts.map +1 -0
  72. package/dist/hosted-service/providers/feishu.js +72 -0
  73. package/dist/hosted-service/providers/feishu.js.map +1 -0
  74. package/dist/hosted-service/providers/github.d.ts +4 -0
  75. package/dist/hosted-service/providers/github.d.ts.map +1 -0
  76. package/dist/hosted-service/providers/github.js +73 -0
  77. package/dist/hosted-service/providers/github.js.map +1 -0
  78. package/dist/hosted-service/providers/google.d.ts +4 -0
  79. package/dist/hosted-service/providers/google.d.ts.map +1 -0
  80. package/dist/hosted-service/providers/google.js +54 -0
  81. package/dist/hosted-service/providers/google.js.map +1 -0
  82. package/dist/hosted-service/routes.d.ts +12 -0
  83. package/dist/hosted-service/routes.d.ts.map +1 -0
  84. package/dist/hosted-service/routes.js +61 -0
  85. package/dist/hosted-service/routes.js.map +1 -0
  86. package/dist/hosted-service/service.d.ts +16 -0
  87. package/dist/hosted-service/service.d.ts.map +1 -0
  88. package/dist/hosted-service/service.js +205 -0
  89. package/dist/hosted-service/service.js.map +1 -0
  90. package/dist/hosted-service/session.d.ts +11 -0
  91. package/dist/hosted-service/session.d.ts.map +1 -0
  92. package/dist/hosted-service/session.js +52 -0
  93. package/dist/hosted-service/session.js.map +1 -0
  94. package/dist/hosted-service/store/file.d.ts +6 -0
  95. package/dist/hosted-service/store/file.d.ts.map +1 -0
  96. package/dist/hosted-service/store/file.js +62 -0
  97. package/dist/hosted-service/store/file.js.map +1 -0
  98. package/dist/hosted-service/store/index.d.ts +6 -0
  99. package/dist/hosted-service/store/index.d.ts.map +1 -0
  100. package/dist/hosted-service/store/index.js +3 -0
  101. package/dist/hosted-service/store/index.js.map +1 -0
  102. package/dist/hosted-service/store/memory.d.ts +6 -0
  103. package/dist/hosted-service/store/memory.d.ts.map +1 -0
  104. package/dist/hosted-service/store/memory.js +19 -0
  105. package/dist/hosted-service/store/memory.js.map +1 -0
  106. package/dist/hosted-service/store/state.d.ts +9 -0
  107. package/dist/hosted-service/store/state.d.ts.map +1 -0
  108. package/dist/hosted-service/store/state.js +156 -0
  109. package/dist/hosted-service/store/state.js.map +1 -0
  110. package/dist/hosted-service/store/types.d.ts +56 -0
  111. package/dist/hosted-service/store/types.d.ts.map +1 -0
  112. package/dist/hosted-service/store/types.js +2 -0
  113. package/dist/hosted-service/store/types.js.map +1 -0
  114. package/dist/hosted-service/types.d.ts +48 -0
  115. package/dist/hosted-service/types.d.ts.map +1 -0
  116. package/dist/hosted-service/types.js +2 -0
  117. package/dist/hosted-service/types.js.map +1 -0
  118. package/dist/hosted-service-cli.d.ts +2 -0
  119. package/dist/hosted-service-cli.d.ts.map +1 -0
  120. package/dist/hosted-service-cli.js +89 -0
  121. package/dist/hosted-service-cli.js.map +1 -0
  122. package/dist/hosted-service-node.d.ts +7 -0
  123. package/dist/hosted-service-node.d.ts.map +1 -0
  124. package/dist/hosted-service-node.js +35 -0
  125. package/dist/hosted-service-node.js.map +1 -0
  126. package/dist/index.d.ts +10 -0
  127. package/dist/index.d.ts.map +1 -0
  128. package/dist/index.js +6 -0
  129. package/dist/index.js.map +1 -0
  130. package/package.json +39 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applications.js","sourceRoot":"","sources":["../../src/hosted-service/applications.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGnD,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,OAAO,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAiC,EAAE,QAAiB;IACjF,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC;IAChD,MAAM,QAAQ,GAA0B;QACtC,QAAQ,EAAE,QAAQ,IAAI,iBAAiB;QACvC,IAAI,EAAE,QAAQ,IAAI,aAAa;KAChC,CAAC;IAEF,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC;AAC9F,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAgB,EAAE,OAAiC;IAC7E,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAEjC,OAAO,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAgB,EAAE,GAA0B;IACzE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAEjC,OAAO,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;AACxG,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,WAAmB,EAAE,GAA0B;IAC/E,IAAI,CAAC,GAAG,CAAC,mBAAmB,EAAE,MAAM,EAAE,CAAC;QACrC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,GAAG,CAAC,mBAAmB,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,WAAmB,EACnB,QAAwC,EACxC,QAAgB,EAChB,WAAmB;IAEnB,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,aAAa,QAAQ,QAAQ,EAAE,WAAW,CAAC,CAAC;IAErE,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IACjD,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;IAEvD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export declare const AUTH_SERVICE_SESSION_COOKIE = "unified_auth_session";
2
+ export declare const AUTH_SERVICE_STATE_COOKIE = "unified_auth_state";
3
+ export declare const SESSION_MAX_AGE_SECONDS: number;
4
+ export declare const STATE_MAX_AGE_SECONDS: number;
5
+ export declare const DEFAULT_CLIENT_ID = "default";
6
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/hosted-service/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,2BAA2B,yBAAyB,CAAC;AAClE,eAAO,MAAM,yBAAyB,uBAAuB,CAAC;AAE9D,eAAO,MAAM,uBAAuB,QAAmB,CAAC;AACxD,eAAO,MAAM,qBAAqB,QAAU,CAAC;AAC7C,eAAO,MAAM,iBAAiB,YAAY,CAAC"}
@@ -0,0 +1,6 @@
1
+ export const AUTH_SERVICE_SESSION_COOKIE = "unified_auth_session";
2
+ export const AUTH_SERVICE_STATE_COOKIE = "unified_auth_state";
3
+ export const SESSION_MAX_AGE_SECONDS = 60 * 60 * 24 * 7;
4
+ export const STATE_MAX_AGE_SECONDS = 60 * 10;
5
+ export const DEFAULT_CLIENT_ID = "default";
6
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/hosted-service/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,2BAA2B,GAAG,sBAAsB,CAAC;AAClE,MAAM,CAAC,MAAM,yBAAyB,GAAG,oBAAoB,CAAC;AAE9D,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AACxD,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,GAAG,EAAE,CAAC;AAC7C,MAAM,CAAC,MAAM,iBAAiB,GAAG,SAAS,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { HostedAuthServiceOptions, SessionPayload } from "./types.js";
2
+ export declare function appendCookie(headers: Headers, cookie: string): void;
3
+ export declare function getCookie(request: Request, name: string): string | undefined;
4
+ export declare function shouldUseSecureCookie(request: Request): boolean;
5
+ export declare function serializeCookie(params: {
6
+ domain?: string;
7
+ httpOnly?: boolean;
8
+ maxAge?: number;
9
+ name: string;
10
+ path?: string;
11
+ sameSite?: "Lax" | "None" | "Strict";
12
+ secure?: boolean;
13
+ value: string;
14
+ }): string;
15
+ export declare function clearCookie(request: Request, options: HostedAuthServiceOptions, name: string): string;
16
+ export declare function createSessionCookie(request: Request, options: HostedAuthServiceOptions, payload: SessionPayload): string;
17
+ //# sourceMappingURL=cookies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookies.d.ts","sourceRoot":"","sources":["../../src/hosted-service/cookies.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,wBAAwB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE3E,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAE5D;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,sBASvD;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,WAQrD;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAC;IACrC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf,UAaA;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,wBAAwB,EAAE,IAAI,EAAE,MAAM,UAQ5F;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,wBAAwB,EACjC,OAAO,EAAE,cAAc,UASxB"}
@@ -0,0 +1,56 @@
1
+ import { AUTH_SERVICE_SESSION_COOKIE, SESSION_MAX_AGE_SECONDS } from "./constants.js";
2
+ import { createSignedToken } from "./crypto.js";
3
+ export function appendCookie(headers, cookie) {
4
+ headers.append("set-cookie", cookie);
5
+ }
6
+ export function getCookie(request, name) {
7
+ const cookie = request.headers.get("cookie") ?? "";
8
+ const prefix = `${name}=`;
9
+ const item = cookie
10
+ .split(";")
11
+ .map((part) => part.trim())
12
+ .find((part) => part.startsWith(prefix));
13
+ return item ? decodeURIComponent(item.slice(prefix.length)) : undefined;
14
+ }
15
+ export function shouldUseSecureCookie(request) {
16
+ const forwardedProto = request.headers.get("x-forwarded-proto")?.split(",")[0]?.trim();
17
+ if (forwardedProto) {
18
+ return forwardedProto === "https";
19
+ }
20
+ return new URL(request.url).protocol === "https:";
21
+ }
22
+ export function serializeCookie(params) {
23
+ const parts = [
24
+ `${params.name}=${encodeURIComponent(params.value)}`,
25
+ `Path=${params.path ?? "/"}`,
26
+ `SameSite=${params.sameSite ?? "Lax"}`,
27
+ ];
28
+ if (params.httpOnly ?? true)
29
+ parts.push("HttpOnly");
30
+ if (typeof params.maxAge === "number")
31
+ parts.push(`Max-Age=${params.maxAge}`);
32
+ if (params.domain)
33
+ parts.push(`Domain=${params.domain}`);
34
+ if (params.secure)
35
+ parts.push("Secure");
36
+ return parts.join("; ");
37
+ }
38
+ export function clearCookie(request, options, name) {
39
+ return serializeCookie({
40
+ domain: options.cookieDomain,
41
+ maxAge: 0,
42
+ name,
43
+ secure: shouldUseSecureCookie(request),
44
+ value: "",
45
+ });
46
+ }
47
+ export function createSessionCookie(request, options, payload) {
48
+ return serializeCookie({
49
+ domain: options.cookieDomain,
50
+ maxAge: SESSION_MAX_AGE_SECONDS,
51
+ name: options.cookieName ?? AUTH_SERVICE_SESSION_COOKIE,
52
+ secure: shouldUseSecureCookie(request),
53
+ value: createSignedToken(payload, options.sessionSecret),
54
+ });
55
+ }
56
+ //# sourceMappingURL=cookies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookies.js","sourceRoot":"","sources":["../../src/hosted-service/cookies.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function createSignedToken(payload: unknown, secret: string): string;
2
+ export declare function parseSignedToken<T>(token: string | undefined, secret: string): T | null;
3
+ //# sourceMappingURL=crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/hosted-service/crypto.ts"],"names":[],"mappings":"AA6BA,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,UAKjE;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAYvF"}
@@ -0,0 +1,39 @@
1
+ import { createHmac, timingSafeEqual } from "node:crypto";
2
+ function encodePayload(value) {
3
+ return Buffer.from(JSON.stringify(value)).toString("base64url");
4
+ }
5
+ function decodePayload(value) {
6
+ try {
7
+ return JSON.parse(Buffer.from(value, "base64url").toString("utf8"));
8
+ }
9
+ catch {
10
+ return null;
11
+ }
12
+ }
13
+ function signPayload(payload, secret) {
14
+ return createHmac("sha256", secret).update(payload).digest("base64url");
15
+ }
16
+ function safeEqual(left, right) {
17
+ const leftBuffer = Buffer.from(left);
18
+ const rightBuffer = Buffer.from(right);
19
+ if (leftBuffer.length !== rightBuffer.length) {
20
+ return false;
21
+ }
22
+ return timingSafeEqual(leftBuffer, rightBuffer);
23
+ }
24
+ export function createSignedToken(payload, secret) {
25
+ const encodedPayload = encodePayload(payload);
26
+ const signature = signPayload(encodedPayload, secret);
27
+ return `${encodedPayload}.${signature}`;
28
+ }
29
+ export function parseSignedToken(token, secret) {
30
+ if (!token) {
31
+ return null;
32
+ }
33
+ const [payload, signature] = token.split(".");
34
+ if (!payload || !signature || !safeEqual(signPayload(payload, secret), signature)) {
35
+ return null;
36
+ }
37
+ return decodePayload(payload);
38
+ }
39
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/hosted-service/crypto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE1D,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAClE,CAAC;AAED,SAAS,aAAa,CAAI,KAAa;IACrC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAM,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,OAAe,EAAE,MAAc;IAClD,OAAO,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AAC1E,CAAC;AAED,SAAS,SAAS,CAAC,IAAY,EAAE,KAAa;IAC5C,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAEvC,IAAI,UAAU,CAAC,MAAM,KAAK,WAAW,CAAC,MAAM,EAAE,CAAC;QAC7C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,eAAe,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAgB,EAAE,MAAc;IAChE,MAAM,cAAc,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,WAAW,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IAEtD,OAAO,GAAG,cAAc,IAAI,SAAS,EAAE,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAI,KAAyB,EAAE,MAAc;IAC3E,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAE9C,IAAI,CAAC,OAAO,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,SAAS,CAAC,EAAE,CAAC;QAClF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,aAAa,CAAI,OAAO,CAAC,CAAC;AACnC,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function html(content: string, init?: ResponseInit): Response;
2
+ export declare function json(data: unknown, init?: ResponseInit): Response;
3
+ export declare function redirect(url: string, headers?: Headers): Response;
4
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/hosted-service/http.ts"],"names":[],"mappings":"AAAA,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY,YAQxD;AAED,wBAAgB,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,YAAY,YAQtD;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,YAStD"}
@@ -0,0 +1,27 @@
1
+ export function html(content, init) {
2
+ return new Response(content, {
3
+ ...init,
4
+ headers: {
5
+ "content-type": "text/html; charset=utf-8",
6
+ ...init?.headers,
7
+ },
8
+ });
9
+ }
10
+ export function json(data, init) {
11
+ return new Response(JSON.stringify(data), {
12
+ ...init,
13
+ headers: {
14
+ "content-type": "application/json; charset=utf-8",
15
+ ...init?.headers,
16
+ },
17
+ });
18
+ }
19
+ export function redirect(url, headers) {
20
+ const responseHeaders = new Headers(headers);
21
+ responseHeaders.set("location", url);
22
+ return new Response(null, {
23
+ headers: responseHeaders,
24
+ status: 302,
25
+ });
26
+ }
27
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/hosted-service/http.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,IAAI,CAAC,OAAe,EAAE,IAAmB;IACvD,OAAO,IAAI,QAAQ,CAAC,OAAO,EAAE;QAC3B,GAAG,IAAI;QACP,OAAO,EAAE;YACP,cAAc,EAAE,0BAA0B;YAC1C,GAAG,IAAI,EAAE,OAAO;SACjB;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,IAAa,EAAE,IAAmB;IACrD,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE;QACxC,GAAG,IAAI;QACP,OAAO,EAAE;YACP,cAAc,EAAE,iCAAiC;YACjD,GAAG,IAAI,EAAE,OAAO;SACjB;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,GAAW,EAAE,OAAiB;IACrD,MAAM,eAAe,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAE7C,eAAe,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IAErC,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE;QACxB,OAAO,EAAE,eAAe;QACxB,MAAM,EAAE,GAAG;KACZ,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { LoginPageLinks, LoginProviderView } from "./types.js";
2
+ export declare function renderBrand(): string;
3
+ export declare function renderError(error?: string): string;
4
+ export declare function renderProviderList(providers: LoginProviderView[]): string;
5
+ export declare function renderDevLogin(allowDevLogin: boolean, links: LoginPageLinks): string;
6
+ export declare function renderFooter(clientId: string): string;
7
+ //# sourceMappingURL=components.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../../src/hosted-service/login-page/components.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpE,wBAAgB,WAAW,WAM1B;AAED,wBAAgB,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,UAEzC;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,iBAAiB,EAAE,UAKhE;AAED,wBAAgB,cAAc,CAAC,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,UAM3E;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,UAK5C"}
@@ -0,0 +1,40 @@
1
+ import { escapeHtml } from "./escape.js";
2
+ export function renderBrand() {
3
+ return `
4
+ <div class="brand-row">
5
+ <div class="mark">AUTH</div>
6
+ <div class="brand-title">统一认证中心</div>
7
+ </div>`;
8
+ }
9
+ export function renderError(error) {
10
+ return error ? `<div class="error">${escapeHtml(error)}</div>` : "";
11
+ }
12
+ export function renderProviderList(providers) {
13
+ return `
14
+ <section class="provider-list" aria-label="登录身份提供方">
15
+ ${providers.map(renderProviderTile).join("\n")}
16
+ </section>`;
17
+ }
18
+ export function renderDevLogin(allowDevLogin, links) {
19
+ if (!allowDevLogin) {
20
+ return "";
21
+ }
22
+ return `<a class="dev-link" href="${escapeHtml(links.devLogin)}">使用开发账号进入</a>`;
23
+ }
24
+ export function renderFooter(clientId) {
25
+ return `
26
+ <div class="footer-row">
27
+ <span>client_id: ${escapeHtml(clientId)}</span>
28
+ </div>`;
29
+ }
30
+ function renderProviderTile(provider) {
31
+ const disabledClass = provider.enabled ? "" : "disabled";
32
+ return `
33
+ <a class="provider-option ${disabledClass}" href="${escapeHtml(provider.href)}">
34
+ <span class="provider-icon ${provider.iconClassName}">${provider.icon}</span>
35
+ <span class="provider-copy">
36
+ <span class="provider-name">${escapeHtml(provider.label)}</span>
37
+ </span>
38
+ </a>`;
39
+ }
40
+ //# sourceMappingURL=components.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.js","sourceRoot":"","sources":["../../../src/hosted-service/login-page/components.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,MAAM,UAAU,WAAW;IACzB,OAAO;;;;WAIE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,OAAO,KAAK,CAAC,CAAC,CAAC,sBAAsB,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,SAA8B;IAC/D,OAAO;;QAED,SAAS,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;eACrC,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,aAAsB,EAAE,KAAqB;IAC1E,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,6BAA6B,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,gBAAgB,CAAC;AACjF,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,OAAO;;yBAEgB,UAAU,CAAC,QAAQ,CAAC;WAClC,CAAC;AACZ,CAAC;AAED,SAAS,kBAAkB,CAAC,QAA2B;IACrD,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC;IAEzD,OAAO;kCACyB,aAAa,WAAW,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;qCAC9C,QAAQ,CAAC,aAAa,KAAK,QAAQ,CAAC,IAAI;;wCAErC,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC;;WAEvD,CAAC;AACZ,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function renderDocument(params: {
2
+ body: string;
3
+ title: string;
4
+ }): string;
5
+ //# sourceMappingURL=document.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../../src/hosted-service/login-page/document.ts"],"names":[],"mappings":"AAIA,wBAAgB,cAAc,CAAC,MAAM,EAAE;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,UAcA"}
@@ -0,0 +1,19 @@
1
+ import { escapeHtml } from "./escape.js";
2
+ import { faviconHref } from "./icons.js";
3
+ import { loginPageStyles } from "./styles.js";
4
+ export function renderDocument(params) {
5
+ return `<!doctype html>
6
+ <html lang="zh-CN">
7
+ <head>
8
+ <meta charset="utf-8" />
9
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
10
+ <link rel="icon" href="${faviconHref}" />
11
+ <title>${escapeHtml(params.title)}</title>
12
+ <style>${loginPageStyles}</style>
13
+ </head>
14
+ <body>
15
+ ${params.body}
16
+ </body>
17
+ </html>`;
18
+ }
19
+ //# sourceMappingURL=document.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document.js","sourceRoot":"","sources":["../../../src/hosted-service/login-page/document.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,UAAU,cAAc,CAAC,MAG9B;IACC,OAAO;;;;;2BAKkB,WAAW;WAC3B,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC;WACxB,eAAe;;;EAGxB,MAAM,CAAC,IAAI;;QAEL,CAAC;AACT,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function escapeHtml(value: string): string;
2
+ //# sourceMappingURL=escape.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape.d.ts","sourceRoot":"","sources":["../../../src/hosted-service/login-page/escape.ts"],"names":[],"mappings":"AAAA,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,UAOvC"}
@@ -0,0 +1,9 @@
1
+ export function escapeHtml(value) {
2
+ return value
3
+ .replaceAll("&", "&amp;")
4
+ .replaceAll("<", "&lt;")
5
+ .replaceAll(">", "&gt;")
6
+ .replaceAll('"', "&quot;")
7
+ .replaceAll("'", "&#39;");
8
+ }
9
+ //# sourceMappingURL=escape.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape.js","sourceRoot":"","sources":["../../../src/hosted-service/login-page/escape.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,KAAK;SACT,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;SACxB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC;SACzB,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare const faviconHref = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='7' fill='%231677ff'/%3E%3Cpath d='M10 17h7l-2 7 8-11h-7l2-6-8 10z' fill='white'/%3E%3C/svg%3E";
2
+ export declare const feishuIcon = "\n<svg viewBox=\"0 0 48 48\" aria-hidden=\"true\">\n <rect x=\"6\" y=\"6\" width=\"17\" height=\"17\" rx=\"5\" fill=\"#2F80ED\"/>\n <rect x=\"25\" y=\"6\" width=\"17\" height=\"17\" rx=\"5\" fill=\"#00B96B\"/>\n <rect x=\"6\" y=\"25\" width=\"17\" height=\"17\" rx=\"5\" fill=\"#12C2E9\"/>\n <rect x=\"25\" y=\"25\" width=\"17\" height=\"17\" rx=\"5\" fill=\"#8B5CF6\"/>\n</svg>";
3
+ export declare const googleIcon = "\n<svg viewBox=\"0 0 48 48\" aria-hidden=\"true\">\n <path fill=\"#EA4335\" d=\"M24 9.5c3.5 0 6.2 1.4 8.2 3.2l6-6C34.5 3.3 29.7 1.2 24 1.2 14.7 1.2 6.7 6.5 2.8 14.2l7 5.4C11.5 13.7 17 9.5 24 9.5z\"/>\n <path fill=\"#4285F4\" d=\"M46.1 24.5c0-1.6-.1-2.8-.4-4.1H24v8.2h12.7c-.3 2.1-1.7 5.2-4.8 7.3l7.2 5.6c4.2-3.9 7-9.6 7-17z\"/>\n <path fill=\"#FBBC05\" d=\"M9.8 28.4c-.5-1.4-.8-2.9-.8-4.4s.3-3 .8-4.4l-7-5.4C1.2 17.1.4 20.4.4 24s.8 6.9 2.4 9.8l7-5.4z\"/>\n <path fill=\"#34A853\" d=\"M24 46.8c5.7 0 10.5-1.9 14-5.2l-7.2-5.6c-1.9 1.3-4.4 2.3-6.8 2.3-7 0-12.5-4.2-14.2-10l-7 5.4C6.7 41.5 14.7 46.8 24 46.8z\"/>\n</svg>";
4
+ export declare const githubIcon = "\n<svg viewBox=\"0 0 48 48\" aria-hidden=\"true\">\n <path fill=\"currentColor\" d=\"M24 3.5C12.7 3.5 3.5 12.7 3.5 24c0 9.1 5.9 16.8 14.1 19.5 1 .2 1.4-.4 1.4-1v-3.6c-5.7 1.2-6.9-2.4-6.9-2.4-.9-2.3-2.2-2.9-2.2-2.9-1.9-1.3.1-1.2.1-1.2 2.1.1 3.2 2.1 3.2 2.1 1.8 3.2 4.8 2.3 6 1.8.2-1.3.7-2.3 1.3-2.8-4.6-.5-9.4-2.3-9.4-10.1 0-2.2.8-4.1 2.1-5.5-.2-.5-.9-2.6.2-5.4 0 0 1.7-.6 5.6 2.1 1.6-.4 3.3-.7 5-.7s3.4.2 5 .7c3.9-2.7 5.6-2.1 5.6-2.1 1.1 2.8.4 4.9.2 5.4 1.3 1.4 2.1 3.3 2.1 5.5 0 7.8-4.8 9.6-9.4 10.1.8.7 1.5 2 1.5 4v5c0 .6.4 1.2 1.4 1C38.6 40.8 44.5 33.1 44.5 24 44.5 12.7 35.3 3.5 24 3.5z\"/>\n</svg>";
5
+ //# sourceMappingURL=icons.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../../src/hosted-service/login-page/icons.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,wNAC+L,CAAC;AAExN,eAAO,MAAM,UAAU,mYAMhB,CAAC;AAER,eAAO,MAAM,UAAU,inBAMhB,CAAC;AAER,eAAO,MAAM,UAAU,gmBAGhB,CAAC"}
@@ -0,0 +1,20 @@
1
+ export const faviconHref = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='7' fill='%231677ff'/%3E%3Cpath d='M10 17h7l-2 7 8-11h-7l2-6-8 10z' fill='white'/%3E%3C/svg%3E";
2
+ export const feishuIcon = `
3
+ <svg viewBox="0 0 48 48" aria-hidden="true">
4
+ <rect x="6" y="6" width="17" height="17" rx="5" fill="#2F80ED"/>
5
+ <rect x="25" y="6" width="17" height="17" rx="5" fill="#00B96B"/>
6
+ <rect x="6" y="25" width="17" height="17" rx="5" fill="#12C2E9"/>
7
+ <rect x="25" y="25" width="17" height="17" rx="5" fill="#8B5CF6"/>
8
+ </svg>`;
9
+ export const googleIcon = `
10
+ <svg viewBox="0 0 48 48" aria-hidden="true">
11
+ <path fill="#EA4335" d="M24 9.5c3.5 0 6.2 1.4 8.2 3.2l6-6C34.5 3.3 29.7 1.2 24 1.2 14.7 1.2 6.7 6.5 2.8 14.2l7 5.4C11.5 13.7 17 9.5 24 9.5z"/>
12
+ <path fill="#4285F4" d="M46.1 24.5c0-1.6-.1-2.8-.4-4.1H24v8.2h12.7c-.3 2.1-1.7 5.2-4.8 7.3l7.2 5.6c4.2-3.9 7-9.6 7-17z"/>
13
+ <path fill="#FBBC05" d="M9.8 28.4c-.5-1.4-.8-2.9-.8-4.4s.3-3 .8-4.4l-7-5.4C1.2 17.1.4 20.4.4 24s.8 6.9 2.4 9.8l7-5.4z"/>
14
+ <path fill="#34A853" d="M24 46.8c5.7 0 10.5-1.9 14-5.2l-7.2-5.6c-1.9 1.3-4.4 2.3-6.8 2.3-7 0-12.5-4.2-14.2-10l-7 5.4C6.7 41.5 14.7 46.8 24 46.8z"/>
15
+ </svg>`;
16
+ export const githubIcon = `
17
+ <svg viewBox="0 0 48 48" aria-hidden="true">
18
+ <path fill="currentColor" d="M24 3.5C12.7 3.5 3.5 12.7 3.5 24c0 9.1 5.9 16.8 14.1 19.5 1 .2 1.4-.4 1.4-1v-3.6c-5.7 1.2-6.9-2.4-6.9-2.4-.9-2.3-2.2-2.9-2.2-2.9-1.9-1.3.1-1.2.1-1.2 2.1.1 3.2 2.1 3.2 2.1 1.8 3.2 4.8 2.3 6 1.8.2-1.3.7-2.3 1.3-2.8-4.6-.5-9.4-2.3-9.4-10.1 0-2.2.8-4.1 2.1-5.5-.2-.5-.9-2.6.2-5.4 0 0 1.7-.6 5.6 2.1 1.6-.4 3.3-.7 5-.7s3.4.2 5 .7c3.9-2.7 5.6-2.1 5.6-2.1 1.1 2.8.4 4.9.2 5.4 1.3 1.4 2.1 3.3 2.1 5.5 0 7.8-4.8 9.6-9.4 10.1.8.7 1.5 2 1.5 4v5c0 .6.4 1.2 1.4 1C38.6 40.8 44.5 33.1 44.5 24 44.5 12.7 35.3 3.5 24 3.5z"/>
19
+ </svg>`;
20
+ //# sourceMappingURL=icons.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icons.js","sourceRoot":"","sources":["../../../src/hosted-service/login-page/icons.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GACtB,qNAAqN,CAAC;AAExN,MAAM,CAAC,MAAM,UAAU,GAAG;;;;;;OAMnB,CAAC;AAER,MAAM,CAAC,MAAM,UAAU,GAAG;;;;;;OAMnB,CAAC;AAER,MAAM,CAAC,MAAM,UAAU,GAAG;;;OAGnB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { RenderLoginPageParams } from "./types.js";
2
+ export declare function renderLoginPage(params: RenderLoginPageParams): string;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hosted-service/login-page/index.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAExD,wBAAgB,eAAe,CAAC,MAAM,EAAE,qBAAqB,UAkB5D"}
@@ -0,0 +1,23 @@
1
+ import { renderBrand, renderDevLogin, renderError, renderFooter, renderProviderList, } from "./components.js";
2
+ import { renderDocument } from "./document.js";
3
+ import { escapeHtml } from "./escape.js";
4
+ import { createLoginPageLinks } from "./links.js";
5
+ export function renderLoginPage(params) {
6
+ const title = params.app.name ?? params.clientId;
7
+ const headline = `${title} 统一登录`;
8
+ const links = createLoginPageLinks(params);
9
+ return renderDocument({
10
+ body: `
11
+ <main>
12
+ ${renderBrand()}
13
+ <h1>${escapeHtml(headline)}</h1>
14
+ <p>选择一个身份提供方进入,首次使用会自动完成账号创建和身份绑定。</p>
15
+ ${renderError(params.error)}
16
+ ${renderProviderList(links.providers)}
17
+ ${renderDevLogin(params.allowDevLogin, links)}
18
+ ${renderFooter(params.clientId)}
19
+ </main>`,
20
+ title: headline,
21
+ });
22
+ }
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/hosted-service/login-page/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,cAAc,EACd,WAAW,EACX,YAAY,EACZ,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGlD,MAAM,UAAU,eAAe,CAAC,MAA6B;IAC3D,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC;IACjD,MAAM,QAAQ,GAAG,GAAG,KAAK,OAAO,CAAC;IACjC,MAAM,KAAK,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAE3C,OAAO,cAAc,CAAC;QACpB,IAAI,EAAE;;MAEJ,WAAW,EAAE;UACT,UAAU,CAAC,QAAQ,CAAC;;MAExB,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC;MACzB,kBAAkB,CAAC,KAAK,CAAC,SAAS,CAAC;MACnC,cAAc,CAAC,MAAM,CAAC,aAAa,EAAE,KAAK,CAAC;MAC3C,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC;UACzB;QACN,KAAK,EAAE,QAAQ;KAChB,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { LoginPageLinks, RenderLoginPageParams } from "./types.js";
2
+ export declare function createLoginPageLinks(params: RenderLoginPageParams): LoginPageLinks;
3
+ //# sourceMappingURL=links.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"links.d.ts","sourceRoot":"","sources":["../../../src/hosted-service/login-page/links.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAqB,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAoC3F,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,qBAAqB,GAAG,cAAc,CA8BlF"}
@@ -0,0 +1,50 @@
1
+ import { createProviderStartUrl } from "../applications.js";
2
+ import { feishuIcon, githubIcon, googleIcon } from "./icons.js";
3
+ function createDevLoginUrl(params) {
4
+ const devUrl = new URL("/api/auth/dev-login", params.authBaseURL);
5
+ devUrl.searchParams.set("client_id", params.clientId);
6
+ devUrl.searchParams.set("redirect_uri", params.redirectURI);
7
+ return devUrl.toString();
8
+ }
9
+ function createProvider(params) {
10
+ return {
11
+ enabled: params.enabled,
12
+ href: createProviderStartUrl(params.authBaseURL, params.id, params.clientId, params.redirectURI).toString(),
13
+ icon: params.icon,
14
+ iconClassName: params.iconClassName,
15
+ id: params.id,
16
+ label: params.label,
17
+ };
18
+ }
19
+ export function createLoginPageLinks(params) {
20
+ return {
21
+ devLogin: createDevLoginUrl(params),
22
+ providers: [
23
+ createProvider({
24
+ ...params,
25
+ enabled: params.feishuEnabled,
26
+ icon: feishuIcon,
27
+ iconClassName: "provider-icon-feishu",
28
+ id: "feishu",
29
+ label: "飞书",
30
+ }),
31
+ createProvider({
32
+ ...params,
33
+ enabled: params.googleEnabled,
34
+ icon: googleIcon,
35
+ iconClassName: "provider-icon-google",
36
+ id: "google",
37
+ label: "Google",
38
+ }),
39
+ createProvider({
40
+ ...params,
41
+ enabled: params.githubEnabled,
42
+ icon: githubIcon,
43
+ iconClassName: "provider-icon-github",
44
+ id: "github",
45
+ label: "GitHub",
46
+ }),
47
+ ],
48
+ };
49
+ }
50
+ //# sourceMappingURL=links.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"links.js","sourceRoot":"","sources":["../../../src/hosted-service/login-page/links.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGhE,SAAS,iBAAiB,CAAC,MAA6B;IACtD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,qBAAqB,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;IAElE,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACtD,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;IAE5D,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC;AAC3B,CAAC;AAED,SAAS,cAAc,CAAC,MASvB;IACC,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,IAAI,EAAE,sBAAsB,CAC1B,MAAM,CAAC,WAAW,EAClB,MAAM,CAAC,EAAE,EACT,MAAM,CAAC,QAAQ,EACf,MAAM,CAAC,WAAW,CACnB,CAAC,QAAQ,EAAE;QACZ,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,KAAK,EAAE,MAAM,CAAC,KAAK;KACpB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAA6B;IAChE,OAAO;QACL,QAAQ,EAAE,iBAAiB,CAAC,MAAM,CAAC;QACnC,SAAS,EAAE;YACT,cAAc,CAAC;gBACb,GAAG,MAAM;gBACT,OAAO,EAAE,MAAM,CAAC,aAAa;gBAC7B,IAAI,EAAE,UAAU;gBAChB,aAAa,EAAE,sBAAsB;gBACrC,EAAE,EAAE,QAAQ;gBACZ,KAAK,EAAE,IAAI;aACZ,CAAC;YACF,cAAc,CAAC;gBACb,GAAG,MAAM;gBACT,OAAO,EAAE,MAAM,CAAC,aAAa;gBAC7B,IAAI,EAAE,UAAU;gBAChB,aAAa,EAAE,sBAAsB;gBACrC,EAAE,EAAE,QAAQ;gBACZ,KAAK,EAAE,QAAQ;aAChB,CAAC;YACF,cAAc,CAAC;gBACb,GAAG,MAAM;gBACT,OAAO,EAAE,MAAM,CAAC,aAAa;gBAC7B,IAAI,EAAE,UAAU;gBAChB,aAAa,EAAE,sBAAsB;gBACrC,EAAE,EAAE,QAAQ;gBACZ,KAAK,EAAE,QAAQ;aAChB,CAAC;SACH;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const loginPageStyles = "\n:root { color-scheme: light; font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif; }\n* { box-sizing: border-box; }\nbody { margin: 0; min-height: 100vh; display: grid; place-items: center; background: #f4f6fa; color: #111827; }\nmain { width: min(440px, calc(100vw - 32px)); background: #fff; border: 1px solid #e3e7ef; border-radius: 8px; padding: 28px; box-shadow: 0 18px 50px rgb(15 23 42 / 10%); }\n.brand-row { display: flex; align-items: center; gap: 12px; margin-bottom: 24px; }\n.mark { width: 42px; height: 42px; display: grid; place-items: center; border-radius: 8px; background: #1677ff; color: #fff; font-weight: 700; font-size: 13px; }\n.brand-title { font-size: 14px; color: #4b5563; }\nh1 { font-size: 24px; line-height: 1.25; margin: 0 0 8px; }\np { margin: 0 0 22px; color: #4b5563; line-height: 1.7; }\na { min-height: 44px; display: flex; align-items: center; justify-content: center; border-radius: 6px; text-decoration: none; font-weight: 600; }\n.provider-list { display: grid; grid-template-columns: repeat(3, minmax(86px, 1fr)); gap: 12px; }\n.provider-option { min-height: 116px; flex-direction: column; gap: 10px; padding: 14px 8px 12px; border: 1px solid #e5e7eb; color: #111827; background: #fff; text-align: center; }\n.provider-option:hover { border-color: #8fb2ff; background: #f8fbff; transform: translateY(-1px); box-shadow: 0 10px 24px rgb(15 23 42 / 8%); }\n.provider-icon { width: 52px; height: 52px; display: grid; place-items: center; border-radius: 8px; flex: 0 0 auto; }\n.provider-icon svg { width: 34px; height: 34px; display: block; }\n.provider-icon-feishu { background: #eef6ff; }\n.provider-icon-google { background: #fff; border: 1px solid #edf0f5; }\n.provider-icon-github { background: #24292f; color: #fff; }\n.provider-copy { display: flex; flex-direction: column; gap: 4px; line-height: 1.15; min-width: 0; }\n.provider-name { font-size: 14px; white-space: nowrap; }\n.dev-link { height: 42px; margin-top: 12px; background: #f3f4f6; color: #111827; }\n.disabled { opacity: .45; pointer-events: none; }\n.error { border: 1px solid #fecaca; color: #991b1b; background: #fef2f2; border-radius: 6px; padding: 10px 12px; margin-bottom: 16px; }\n.footer-row { margin-top: 18px; color: #6b7280; font-size: 12px; }\n@media (max-width: 420px) {\n main { padding: 22px; }\n h1 { font-size: 22px; }\n .provider-list { gap: 8px; }\n .provider-option { min-height: 106px; }\n .provider-icon { width: 46px; height: 46px; }\n .provider-icon svg { width: 30px; height: 30px; }\n}\n";
2
+ //# sourceMappingURL=styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../src/hosted-service/login-page/styles.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,u/EAiC3B,CAAC"}
@@ -0,0 +1,35 @@
1
+ export const loginPageStyles = `
2
+ :root { color-scheme: light; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }
3
+ * { box-sizing: border-box; }
4
+ body { margin: 0; min-height: 100vh; display: grid; place-items: center; background: #f4f6fa; color: #111827; }
5
+ main { width: min(440px, calc(100vw - 32px)); background: #fff; border: 1px solid #e3e7ef; border-radius: 8px; padding: 28px; box-shadow: 0 18px 50px rgb(15 23 42 / 10%); }
6
+ .brand-row { display: flex; align-items: center; gap: 12px; margin-bottom: 24px; }
7
+ .mark { width: 42px; height: 42px; display: grid; place-items: center; border-radius: 8px; background: #1677ff; color: #fff; font-weight: 700; font-size: 13px; }
8
+ .brand-title { font-size: 14px; color: #4b5563; }
9
+ h1 { font-size: 24px; line-height: 1.25; margin: 0 0 8px; }
10
+ p { margin: 0 0 22px; color: #4b5563; line-height: 1.7; }
11
+ a { min-height: 44px; display: flex; align-items: center; justify-content: center; border-radius: 6px; text-decoration: none; font-weight: 600; }
12
+ .provider-list { display: grid; grid-template-columns: repeat(3, minmax(86px, 1fr)); gap: 12px; }
13
+ .provider-option { min-height: 116px; flex-direction: column; gap: 10px; padding: 14px 8px 12px; border: 1px solid #e5e7eb; color: #111827; background: #fff; text-align: center; }
14
+ .provider-option:hover { border-color: #8fb2ff; background: #f8fbff; transform: translateY(-1px); box-shadow: 0 10px 24px rgb(15 23 42 / 8%); }
15
+ .provider-icon { width: 52px; height: 52px; display: grid; place-items: center; border-radius: 8px; flex: 0 0 auto; }
16
+ .provider-icon svg { width: 34px; height: 34px; display: block; }
17
+ .provider-icon-feishu { background: #eef6ff; }
18
+ .provider-icon-google { background: #fff; border: 1px solid #edf0f5; }
19
+ .provider-icon-github { background: #24292f; color: #fff; }
20
+ .provider-copy { display: flex; flex-direction: column; gap: 4px; line-height: 1.15; min-width: 0; }
21
+ .provider-name { font-size: 14px; white-space: nowrap; }
22
+ .dev-link { height: 42px; margin-top: 12px; background: #f3f4f6; color: #111827; }
23
+ .disabled { opacity: .45; pointer-events: none; }
24
+ .error { border: 1px solid #fecaca; color: #991b1b; background: #fef2f2; border-radius: 6px; padding: 10px 12px; margin-bottom: 16px; }
25
+ .footer-row { margin-top: 18px; color: #6b7280; font-size: 12px; }
26
+ @media (max-width: 420px) {
27
+ main { padding: 22px; }
28
+ h1 { font-size: 22px; }
29
+ .provider-list { gap: 8px; }
30
+ .provider-option { min-height: 106px; }
31
+ .provider-icon { width: 46px; height: 46px; }
32
+ .provider-icon svg { width: 30px; height: 30px; }
33
+ }
34
+ `;
35
+ //# sourceMappingURL=styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.js","sourceRoot":"","sources":["../../../src/hosted-service/login-page/styles.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiC9B,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { HostedAuthApplication } from "../types.js";
2
+ export type LoginProviderId = "feishu" | "github" | "google";
3
+ export type LoginProviderView = {
4
+ enabled: boolean;
5
+ href: string;
6
+ icon: string;
7
+ iconClassName: string;
8
+ id: LoginProviderId;
9
+ label: string;
10
+ };
11
+ export type LoginPageLinks = {
12
+ devLogin: string;
13
+ providers: LoginProviderView[];
14
+ };
15
+ export type RenderLoginPageParams = {
16
+ allowDevLogin: boolean;
17
+ app: HostedAuthApplication;
18
+ authBaseURL: string;
19
+ clientId: string;
20
+ error?: string;
21
+ feishuEnabled: boolean;
22
+ githubEnabled: boolean;
23
+ googleEnabled: boolean;
24
+ redirectURI: string;
25
+ };
26
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/hosted-service/login-page/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEzD,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE7D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,EAAE,EAAE,eAAe,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,iBAAiB,EAAE,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,aAAa,EAAE,OAAO,CAAC;IACvB,GAAG,EAAE,qBAAqB,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/hosted-service/login-page/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ import type { HostedAuthApplication, HostedAuthServiceOptions, StatePayload } from "./types.js";
2
+ export declare function createOAuthState(app: HostedAuthApplication, redirectURI: string): {
3
+ payload: StatePayload;
4
+ state: string;
5
+ };
6
+ export declare function createOAuthStateCookie(request: Request, options: HostedAuthServiceOptions, payload: StatePayload): string;
7
+ export declare function readOAuthCallbackState(request: Request, options: HostedAuthServiceOptions): {
8
+ code: string;
9
+ savedState: StatePayload;
10
+ } | null;
11
+ //# sourceMappingURL=oauth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/hosted-service/oauth.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEhG,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM;;;EAU/E;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,wBAAwB,EACjC,OAAO,EAAE,YAAY,UAStB;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,wBAAwB;;;SAczF"}