@o3co/create-auth-provider 0.14.0 → 0.16.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.ja.md +93 -47
- package/README.md +92 -46
- package/package.json +1 -1
- package/templates/standalone/.env.example +34 -0
- package/templates/standalone/Dockerfile +1 -1
- package/templates/standalone/README.ja.md +565 -130
- package/templates/standalone/README.md +356 -92
- package/templates/standalone/config/application.conf +77 -2
- package/templates/standalone/docker-compose.production.yml +7 -0
- package/templates/standalone/docker-compose.yml +7 -0
- package/templates/standalone/gitignore +3 -2
- package/templates/standalone/package.json +3 -2
- package/templates/standalone/src/__tests__/access-token-lifetime-alias.test.mts +49 -15
- package/templates/standalone/src/__tests__/all-modules-composition.fixture.mts +1103 -0
- package/templates/standalone/src/__tests__/all-modules-composition.multi.test.mts +241 -0
- package/templates/standalone/src/__tests__/all-modules-composition.test.mts +1100 -0
- package/templates/standalone/src/__tests__/documented-env-overrides.test.mts +40 -5
- package/templates/standalone/src/__tests__/federation-grants-composition.test.mts +445 -0
- package/templates/standalone/src/__tests__/federation-grants-survive-logout.test.mts +446 -0
- package/templates/standalone/src/__tests__/federation-token-refresh-outage.test.mts +133 -0
- package/templates/standalone/src/__tests__/google-federation-config-module.test.mts +85 -0
- package/templates/standalone/src/__tests__/google-session.fixture.mts +304 -0
- package/templates/standalone/src/__tests__/host-routes.test.mts +141 -0
- package/templates/standalone/src/__tests__/listen.test.mts +128 -0
- package/templates/standalone/src/__tests__/logger-projection.test.mts +77 -0
- package/templates/standalone/src/__tests__/metrics.test.mts +20 -5
- package/templates/standalone/src/__tests__/post-logout-redirect.test.mts +187 -0
- package/templates/standalone/src/__tests__/redis-connection-error-log.test.mts +139 -0
- package/templates/standalone/src/__tests__/replica-safety.test.mts +13 -3
- package/templates/standalone/src/__tests__/router-error-answers.test.mts +149 -0
- package/templates/standalone/src/__tests__/scaffold-assets.test.mts +14 -0
- package/templates/standalone/src/__tests__/shutdown.test.mts +253 -22
- package/templates/standalone/src/__tests__/smoke.test.mts +39 -20
- package/templates/standalone/src/__tests__/store-credential.test.mts +276 -0
- package/templates/standalone/src/app.mts +30 -51
- package/templates/standalone/src/buildModules.mts +94 -12
- package/templates/standalone/src/listen.mts +66 -0
- package/templates/standalone/src/logger.mts +7 -4
- package/templates/standalone/src/modules.mts +118 -12
- package/templates/standalone/src/routes.mts +95 -0
- package/templates/standalone/src/shutdown.mts +90 -18
- package/templates/standalone/vitest.supertest-loopback.mts +22 -3
- package/templates/versions.json +15 -14
- package/templates/standalone/src/__tests__/terminal-error.test.mts +0 -96
- package/templates/standalone/src/terminalError.mts +0 -60
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2026 1o1 Co. Ltd.
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
import type { Logger } from "@o3co/auth-provider-core";
|
|
17
|
-
import express from "express";
|
|
18
|
-
import request from "supertest";
|
|
19
|
-
import { describe, expect, it, vi } from "vitest";
|
|
20
|
-
import { createTerminalErrorHandler } from "../terminalError.mjs";
|
|
21
|
-
|
|
22
|
-
const makeLogger = () => {
|
|
23
|
-
const error = vi.fn();
|
|
24
|
-
const logger = {
|
|
25
|
-
error,
|
|
26
|
-
warn: vi.fn(),
|
|
27
|
-
info: vi.fn(),
|
|
28
|
-
debug: vi.fn(),
|
|
29
|
-
} as unknown as Logger;
|
|
30
|
-
return { logger, error };
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const makeApp = (logger: Logger) => {
|
|
34
|
-
const app = express();
|
|
35
|
-
app.use(express.json());
|
|
36
|
-
app.post("/echo", (_req, res) => {
|
|
37
|
-
res.status(200).json({ ok: true });
|
|
38
|
-
});
|
|
39
|
-
app.get("/boom", () => {
|
|
40
|
-
throw new Error("route exploded");
|
|
41
|
-
});
|
|
42
|
-
app.use(createTerminalErrorHandler(logger));
|
|
43
|
-
return app;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
describe("terminal error handler (#293 item 8)", () => {
|
|
47
|
-
it("answers malformed JSON with the client's 400 in the shared envelope, not Express's HTML page", async () => {
|
|
48
|
-
const { logger, error } = makeLogger();
|
|
49
|
-
const res = await request(makeApp(logger))
|
|
50
|
-
.post("/echo")
|
|
51
|
-
.set("Content-Type", "application/json")
|
|
52
|
-
.send("{not json");
|
|
53
|
-
|
|
54
|
-
expect(res.status).toBe(400);
|
|
55
|
-
expect(res.headers["content-type"]).toContain("application/json");
|
|
56
|
-
expect(res.body.error).toBe("invalid_request");
|
|
57
|
-
// The client's malformed body is not a server error worth an error line.
|
|
58
|
-
expect(error).not.toHaveBeenCalled();
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it("keeps the body parser's own status for an over-limit body (413)", async () => {
|
|
62
|
-
const { logger } = makeLogger();
|
|
63
|
-
const app = express();
|
|
64
|
-
app.use(express.json({ limit: 16 }));
|
|
65
|
-
app.post("/echo", (_req, res) => {
|
|
66
|
-
res.status(200).json({ ok: true });
|
|
67
|
-
});
|
|
68
|
-
app.use(createTerminalErrorHandler(logger));
|
|
69
|
-
|
|
70
|
-
const res = await request(app)
|
|
71
|
-
.post("/echo")
|
|
72
|
-
.set("Content-Type", "application/json")
|
|
73
|
-
.send(JSON.stringify({ pad: "x".repeat(64) }));
|
|
74
|
-
|
|
75
|
-
expect(res.status).toBe(413);
|
|
76
|
-
expect(res.body.error).toBe("invalid_request");
|
|
77
|
-
expect(res.body.error_description).toBe("request body too large");
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it("answers an unexpected route throw with 500 server_error and logs it structurally", async () => {
|
|
81
|
-
const { logger, error } = makeLogger();
|
|
82
|
-
const res = await request(makeApp(logger)).get("/boom");
|
|
83
|
-
|
|
84
|
-
expect(res.status).toBe(500);
|
|
85
|
-
expect(res.body).toEqual({
|
|
86
|
-
error: "server_error",
|
|
87
|
-
error_description: "Internal server error",
|
|
88
|
-
});
|
|
89
|
-
// No stack trace on the wire — the envelope is the whole body.
|
|
90
|
-
expect(JSON.stringify(res.body)).not.toContain("route exploded");
|
|
91
|
-
expect(error).toHaveBeenCalledWith(
|
|
92
|
-
expect.objectContaining({ endpoint: "/boom" }),
|
|
93
|
-
"unhandled_request_error",
|
|
94
|
-
);
|
|
95
|
-
});
|
|
96
|
-
});
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2026 1o1 Co. Ltd.
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
import { errorEnvelope, type Logger } from "@o3co/auth-provider-core";
|
|
17
|
-
import type { ErrorRequestHandler } from "express";
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Terminal Express error handler (#293 item 8).
|
|
21
|
-
*
|
|
22
|
-
* Anything a route threw past its own try/catch — and every body-parser
|
|
23
|
-
* rejection, which fires before any route runs — used to fall through to
|
|
24
|
-
* Express's default handler: an HTML 500 outside the structured-log pipeline,
|
|
25
|
-
* carrying a stack trace outside production. A client that parses only the
|
|
26
|
-
* RFC 6749 §5.2 JSON envelope this surface answers with everywhere else has
|
|
27
|
-
* no way to read that page.
|
|
28
|
-
*
|
|
29
|
-
* Body-parser failures (malformed JSON/form, over-limit, bad charset) carry
|
|
30
|
-
* their own 4xx `status` and are the client's fault: keep the status, wrap it
|
|
31
|
-
* in the shared envelope, and do not log them as server errors. Everything
|
|
32
|
-
* else is logged with the request path and answered `500 server_error`.
|
|
33
|
-
*
|
|
34
|
-
* Mount it AFTER every route (`app.use(handle.router)` included) — Express
|
|
35
|
-
* routes errors only to handlers registered later.
|
|
36
|
-
*/
|
|
37
|
-
export const createTerminalErrorHandler = (logger: Logger): ErrorRequestHandler => {
|
|
38
|
-
return (err, req, res, next) => {
|
|
39
|
-
// A failure after the response started is not ours to rewrite; handing
|
|
40
|
-
// it back lets Express close the connection.
|
|
41
|
-
if (res.headersSent) {
|
|
42
|
-
next(err);
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
const status = (err as { status?: unknown; statusCode?: unknown } | null) ?? {};
|
|
46
|
-
const httpStatus =
|
|
47
|
-
typeof status.status === "number"
|
|
48
|
-
? status.status
|
|
49
|
-
: typeof status.statusCode === "number"
|
|
50
|
-
? status.statusCode
|
|
51
|
-
: undefined;
|
|
52
|
-
if (httpStatus !== undefined && httpStatus >= 400 && httpStatus < 500) {
|
|
53
|
-
const description = httpStatus === 413 ? "request body too large" : "malformed request body";
|
|
54
|
-
res.status(httpStatus).json(errorEnvelope("invalid_request", description));
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
logger.error({ err, endpoint: req.path }, "unhandled_request_error");
|
|
58
|
-
res.status(500).json(errorEnvelope("server_error", "Internal server error"));
|
|
59
|
-
};
|
|
60
|
-
};
|