@o3co/create-auth-provider 0.17.0-rc.4 → 0.18.0-rc.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.
Files changed (110) hide show
  1. package/README.md +2 -198
  2. package/main.js +4 -0
  3. package/package.json +8 -30
  4. package/README.ja.md +0 -200
  5. package/dist/cli.d.mts +0 -3
  6. package/dist/cli.d.mts.map +0 -1
  7. package/dist/cli.mjs +0 -18
  8. package/dist/index.d.mts +0 -48
  9. package/dist/index.d.mts.map +0 -1
  10. package/dist/index.mjs +0 -325
  11. package/dist/internal/template-filter.d.mts +0 -14
  12. package/dist/internal/template-filter.d.mts.map +0 -1
  13. package/dist/internal/template-filter.mjs +0 -42
  14. package/templates/standalone/.dockerignore +0 -23
  15. package/templates/standalone/.env.example +0 -152
  16. package/templates/standalone/Dockerfile +0 -125
  17. package/templates/standalone/Makefile +0 -12
  18. package/templates/standalone/README.ja.md +0 -913
  19. package/templates/standalone/README.md +0 -1537
  20. package/templates/standalone/config/application.conf +0 -351
  21. package/templates/standalone/config/clients.yaml +0 -4
  22. package/templates/standalone/config/clients.yaml.example +0 -118
  23. package/templates/standalone/config/development.conf +0 -17
  24. package/templates/standalone/config/mailpit.conf +0 -13
  25. package/templates/standalone/config/production.conf +0 -15
  26. package/templates/standalone/config/reference.conf +0 -424
  27. package/templates/standalone/docker-compose.mailpit.yml +0 -39
  28. package/templates/standalone/docker-compose.production.yml +0 -229
  29. package/templates/standalone/docker-compose.test.yml +0 -16
  30. package/templates/standalone/docker-compose.yml +0 -67
  31. package/templates/standalone/gitignore +0 -23
  32. package/templates/standalone/package.json +0 -55
  33. package/templates/standalone/src/__tests__/adapters.test.mts +0 -425
  34. package/templates/standalone/src/__tests__/admission-lifecycle.test.mts +0 -87
  35. package/templates/standalone/src/__tests__/all-modules-composition.fixture.mts +0 -1192
  36. package/templates/standalone/src/__tests__/all-modules-composition.multi.test.mts +0 -285
  37. package/templates/standalone/src/__tests__/all-modules-composition.test.mts +0 -1154
  38. package/templates/standalone/src/__tests__/audit-sink.test.mts +0 -346
  39. package/templates/standalone/src/__tests__/config-notices.test.mts +0 -157
  40. package/templates/standalone/src/__tests__/configPath.test.mts +0 -69
  41. package/templates/standalone/src/__tests__/configured-mfa-mode.fixture.mts +0 -48
  42. package/templates/standalone/src/__tests__/core-federations.test.mts +0 -252
  43. package/templates/standalone/src/__tests__/core-sections.test.mts +0 -192
  44. package/templates/standalone/src/__tests__/device-code-store-client-module.test.mts +0 -95
  45. package/templates/standalone/src/__tests__/documented-env-overrides.test.mts +0 -1290
  46. package/templates/standalone/src/__tests__/federation-grants-composition.test.mts +0 -784
  47. package/templates/standalone/src/__tests__/federation-grants-survive-logout.test.mts +0 -461
  48. package/templates/standalone/src/__tests__/federation-token-refresh-outage.test.mts +0 -141
  49. package/templates/standalone/src/__tests__/federation-types.test.mts +0 -239
  50. package/templates/standalone/src/__tests__/google-session.fixture.mts +0 -308
  51. package/templates/standalone/src/__tests__/host-routes.test.mts +0 -134
  52. package/templates/standalone/src/__tests__/library-reference-resolution.smoke.test.mts +0 -29
  53. package/templates/standalone/src/__tests__/library-references.fixture.mts +0 -188
  54. package/templates/standalone/src/__tests__/lifecycle-pending-close.test.mts +0 -216
  55. package/templates/standalone/src/__tests__/listen.test.mts +0 -121
  56. package/templates/standalone/src/__tests__/logger-projection.test.mts +0 -77
  57. package/templates/standalone/src/__tests__/logout-session-cookie.test.mts +0 -113
  58. package/templates/standalone/src/__tests__/mail-sender.test.mts +0 -134
  59. package/templates/standalone/src/__tests__/mailpit-compose.test.mts +0 -393
  60. package/templates/standalone/src/__tests__/metrics.test.mts +0 -253
  61. package/templates/standalone/src/__tests__/mfa-routes-budget.test.mts +0 -122
  62. package/templates/standalone/src/__tests__/mfa-switch.redis.test.mts +0 -127
  63. package/templates/standalone/src/__tests__/mfa-switch.test.mts +0 -883
  64. package/templates/standalone/src/__tests__/own-modules.test.mts +0 -1512
  65. package/templates/standalone/src/__tests__/post-logout-redirect.test.mts +0 -183
  66. package/templates/standalone/src/__tests__/redis-assume-noeviction.test.mts +0 -214
  67. package/templates/standalone/src/__tests__/redis-connection-error-log.test.mts +0 -135
  68. package/templates/standalone/src/__tests__/redis-rate-limiter-config-survives.test.mts +0 -214
  69. package/templates/standalone/src/__tests__/refresh-token-family-client-module.test.mts +0 -249
  70. package/templates/standalone/src/__tests__/replica-safety.test.mts +0 -654
  71. package/templates/standalone/src/__tests__/repositories-logger.test.mts +0 -119
  72. package/templates/standalone/src/__tests__/router-error-answers.test.mts +0 -146
  73. package/templates/standalone/src/__tests__/scaffold-assets.test.mts +0 -610
  74. package/templates/standalone/src/__tests__/sections.test.mts +0 -504
  75. package/templates/standalone/src/__tests__/session-lifecycle.test.mts +0 -215
  76. package/templates/standalone/src/__tests__/session-logout-invalidates-token.test.mts +0 -296
  77. package/templates/standalone/src/__tests__/session-logout-lifecycle.test.mts +0 -130
  78. package/templates/standalone/src/__tests__/session-requirements.test.mts +0 -382
  79. package/templates/standalone/src/__tests__/shipped-config-notices.test.mts +0 -274
  80. package/templates/standalone/src/__tests__/shutdown.test.mts +0 -622
  81. package/templates/standalone/src/__tests__/smoke.test.mts +0 -634
  82. package/templates/standalone/src/__tests__/startup-log-lines.test.mts +0 -148
  83. package/templates/standalone/src/__tests__/store-credential.test.mts +0 -312
  84. package/templates/standalone/src/__tests__/supertest-loopback.test.mts +0 -296
  85. package/templates/standalone/src/__tests__/three-tier-resolution.test.mts +0 -265
  86. package/templates/standalone/src/__tests__/two-phase-config.test.mts +0 -605
  87. package/templates/standalone/src/__tests__/upstream-amr.acceptance.test.mts +0 -382
  88. package/templates/standalone/src/adapters.mts +0 -162
  89. package/templates/standalone/src/app.mts +0 -136
  90. package/templates/standalone/src/bootRefusal.mts +0 -117
  91. package/templates/standalone/src/buildModules.mts +0 -358
  92. package/templates/standalone/src/configPath.mts +0 -487
  93. package/templates/standalone/src/listen.mts +0 -60
  94. package/templates/standalone/src/logger.mts +0 -80
  95. package/templates/standalone/src/metrics.mts +0 -167
  96. package/templates/standalone/src/mfaSwitch.mts +0 -284
  97. package/templates/standalone/src/modules.mts +0 -705
  98. package/templates/standalone/src/rootRenames.mts +0 -95
  99. package/templates/standalone/src/routes.mts +0 -89
  100. package/templates/standalone/src/sections.mts +0 -377
  101. package/templates/standalone/src/shutdown.mts +0 -213
  102. package/templates/standalone/tests/Makefile +0 -5
  103. package/templates/standalone/tests/index.test.js +0 -283
  104. package/templates/standalone/tests/package-lock.json +0 -1617
  105. package/templates/standalone/tests/package.json +0 -16
  106. package/templates/standalone/tests/vitest.config.mjs +0 -26
  107. package/templates/standalone/tsconfig.json +0 -31
  108. package/templates/standalone/vitest.config.mts +0 -31
  109. package/templates/standalone/vitest.supertest-loopback.mts +0 -278
  110. package/templates/versions.json +0 -20
package/README.md CHANGED
@@ -1,201 +1,5 @@
1
1
  # @o3co/create-auth-provider
2
2
 
3
- Last updated: 2026-10-06
3
+ Part of auth-provider 0.18.0-rc.1 of https://github.com/o3co/auth.provider. Its modules, settings and documentation are there.
4
4
 
5
- CLI scaffolder for auth.provider. Generates a new server project from one of the built-in templates.
6
-
7
- ## Responsibility
8
-
9
- **Role.** The `npx` entry point that turns one of the in-repo templates under
10
- [`templates/`](../templates) — each a deployable composition root — into a new,
11
- independent project. It runs once, on the operator's machine; nothing in the generated
12
- project imports it, and it imports none of the `packages/*` libraries.
13
-
14
- **Owns.** Project-name, directory and template validation, copying the
15
- chosen template, rewriting the generated `package.json` (name, `workspace:*`
16
- → published versions), writing the project's `pnpm-workspace.yaml`, and the
17
- one-time `pnpm-lock.yaml` resolution.
18
-
19
- **Does not own.** The content of the generated project — source, config,
20
- Dockerfile, tests — which is the template's (edit `templates/<name>`, not
21
- this package); and which templates there are, and what each is for — the
22
- [composition templates ADR](../packages/core/docs/adr/2026-09-29-composition-templates.md).
23
- Runtime behaviour belongs to `@o3co/auth-provider-core` and the libraries the
24
- template depends on.
25
-
26
- **Why a separate package.** It is published on its own with a `bin`, so it can
27
- be run with `npx` without installing the provider. The monorepo is not in the
28
- published tarball, so the package carries its own copy of every template and
29
- of the library versions they pin ([How the templates are bundled](#how-the-templates-are-bundled)).
30
-
31
- ## Usage
32
-
33
- ```bash
34
- npx @o3co/create-auth-provider <project-name> [--template <name>] [--dir <dir-name>] [--no-lockfile] [--no-mfa]
35
- ```
36
-
37
- `--template` names the template to copy, `standalone` by default. The
38
- templates are the directories under [`templates/`](../templates) that hold a
39
- `package.json` (not a symbolic link, not dot-named), and the CLI refuses any
40
- other name, listing the ones it has.
41
- What each template is for is in its own README; how the set is drawn — a
42
- template per composition shape, not per feature — is in the
43
- [composition templates ADR](../packages/core/docs/adr/2026-09-29-composition-templates.md).
44
-
45
- ```bash
46
- npx @o3co/create-auth-provider my-auth-server --template standalone
47
- ```
48
-
49
- `<project-name>` may be either a scoped npm name (`@scope/pkg`) or an unscoped name (`pkg`).
50
-
51
- Unscoped example:
52
-
53
- ```bash
54
- npx @o3co/create-auth-provider my-auth-server
55
- cd my-auth-server
56
- pnpm install
57
- ```
58
-
59
- Scoped example (directory defaults to the package portion `auth.provider`):
60
-
61
- ```bash
62
- npx @o3co/create-auth-provider @my-org/auth.provider
63
- cd auth.provider
64
- pnpm install
65
- ```
66
-
67
- Override the directory name with `--dir`:
68
-
69
- ```bash
70
- npx @o3co/create-auth-provider @my-org/auth.provider --dir provider
71
- cd provider
72
- ```
73
-
74
- `--no-lockfile` skips the lockfile step (step 7 below).
75
-
76
- The scaffold requires a second factor at every password login: the
77
- template's MFA switch, `mfaMode` (`MFA_MODE`), defaults to `required`. In
78
- development that needs nothing more; outside it, the project's boot is
79
- refused until it sets what MFA needs (its two stores on Redis, a key, an SMTP
80
- relay) or turns MFA off with `MFA_MODE=off`. The MFA page defaults to `/mfa`,
81
- which the project must serve, or every password login stops there. What the
82
- switch installs and needs is in the template's README.
83
-
84
- `--no-mfa` writes the switch off in the scaffold instead:
85
- it appends `mfaMode = "off"` and then `mfaMode = ${?MFA_MODE}` to
86
- `config/application.conf`, so the project stays off whatever default a later
87
- template ships, and `MFA_MODE` still turns MFA on without re-scaffolding. The
88
- MFA package stays a dependency; nothing else is removed or changed. The
89
- project's own suite (`pnpm run test`) reads the switch from the project's
90
- configuration and asserts what it implies, so it passes with or without
91
- `--no-mfa`.
92
-
93
- The generated project is a pnpm project: its `Dockerfile` installs with
94
- `pnpm install --frozen-lockfile`, and its build allowlist lives in
95
- `pnpm-workspace.yaml`.
96
-
97
- The CLI's closing message suggests `pnpm run debug` next. On the scaffold's
98
- defaults alone that does not boot: it reads no `.env` file (only the compose
99
- files do), and needs from the shell's environment an issuer
100
- (`OAUTH_JWT_ISSUER`), a signing key pair, a session secret, the two URLs of
101
- your user service (`REPOSITORIES_USER_HTTP_AUTHENTICATE_URL`,
102
- `REPOSITORIES_USER_HTTP_AUTHENTICATE_BY_TOKEN_URL`) and a Redis on `localhost:6379`. The
103
- template's README, which the project carries, gives the commands under
104
- [Usage](../templates/standalone/README.md#usage).
105
-
106
- ## What It Does
107
-
108
- 1. Validates `<project-name>` (see [Validation Rules](#validation-rules)).
109
- 2. Derives the target directory name: `--dir <value>` if given, else the unscoped part of a scoped name, else the name itself.
110
- 3. Checks that `--template` (default `standalone`) names a bundled template, and resolves the target directory as `<cwd>/<dir-name>`, erroring if it already exists.
111
- 4. Copies the named template to the target directory, excluding `node_modules/` and `dist/`, and restores its `.gitignore` (the tarball carries it as `gitignore`, because npm drops a file named `.gitignore` from a published package). With `--no-mfa`, appends the MFA switch lines to its `config/application.conf`.
112
- 5. Rewrites `package.json` in the generated directory:
113
- - Sets `name` to `<project-name>` verbatim (scope-preserving).
114
- - Keeps `"private": true` on purpose: a scaffolded identity provider should not be publishable by accident. Remove the field yourself if you really intend to publish.
115
- - Replaces each `workspace:*` version in `dependencies`, `devDependencies` and `peerDependencies` with `^<version>` from the bundled `versions.json`.
116
- 6. Writes `pnpm-workspace.yaml` with the `onlyBuiltDependencies` allowlist for `bcrypt` — pnpm 10.29 and later read that allowlist only from this file, in a single-package project too.
117
- 7. Resolves the dependency set into `pnpm-lock.yaml` (`pnpm install --lockfile-only --ignore-workspace`, through `corepack pnpm` when `pnpm` is not on `PATH`), unless `--no-lockfile` was passed. This needs a reachable registry; a failure prints a warning and the scaffold still completes.
118
- 8. Prints next-step instructions.
119
-
120
- ### The generated `pnpm-lock.yaml`
121
-
122
- The template's `Dockerfile` installs with `pnpm install --frozen-lockfile`, so
123
- the generated project needs a lockfile to build at all. It cannot ship with the
124
- template: until step 5 has replaced every `workspace:*` with a published
125
- version, the dependency set the lockfile would have to pin does not exist. So
126
- it is resolved once, here, against the rewritten `package.json`. **Commit it** —
127
- it is what makes `docker build` reproducible. If step 7 failed or was skipped,
128
- run `pnpm install` in the project once and commit the result.
129
-
130
- ## How the templates are bundled
131
-
132
- The package's `prebuild` and `prepack` scripts run
133
- [`scripts/copy-templates.mjs`](scripts/copy-templates.mjs), which copies
134
- every template into `create-app/templates/<name>` (git-ignored; `node_modules/`
135
- and `dist/` excluded; the destination is rebuilt whole, so a template removed
136
- from the repository does not linger) and writes `create-app/templates/versions.json`, the current version
137
- of every published `@o3co/auth-provider-*` package. The tarball ships both
138
- (`files: ["dist", "templates"]`), and `scaffold()` reads them from there. A
139
- scaffold is therefore the template as it was when this package was built,
140
- pinned to the library versions of that same build.
141
- What a template is — a directory under `templates/`, not a symbolic link and
142
- not dot-named, holding a `package.json`, named in lowercase kebab-case — is
143
- defined once, in [`scripts/templates.mjs`](scripts/templates.mjs), which the
144
- copy and CI's build of every template both use; the scaffolder's
145
- `availableTemplates()` reads the copy by the same rule.
146
- [`published-package.test.mts`](src/__tests__/published-package.test.mts)
147
- packs the package and holds the tarball to the repository: it must ship every
148
- template, and each must scaffold from it.
149
-
150
- CI runs [`scripts/check-versions-json.mjs`](scripts/check-versions-json.mjs),
151
- which fails when a published package under `packages/` is missing from
152
- `copy-templates.mjs`'s version list, or the list names one that no longer
153
- exists — a scaffold would otherwise fail to resolve that package's
154
- `workspace:*` version.
155
-
156
- ## Validation Rules
157
-
158
- `<project-name>` must match one of:
159
-
160
- - Unscoped: `^[a-z0-9][a-z0-9-._~]*$`
161
- - Scoped: `^@[a-z0-9][a-z0-9-._~]*/[a-z0-9][a-z0-9-._~]*$`
162
-
163
- Both forms must be non-empty, not `.` or `..`, and ≤ 214 characters.
164
-
165
- `--dir <value>` must match the unscoped pattern above (same constraints).
166
-
167
- `--template <name>` must be the name of a bundled template, exactly; a path is
168
- never one. A template's name is lowercase kebab-case,
169
- `^[a-z0-9]+(?:-[a-z0-9]+)*$` (lowercase letters and digits, in parts joined by
170
- single hyphens); the build refuses a template named otherwise.
171
-
172
- ## Known Limitations
173
-
174
- - Each bundled template's `README.md` / `README.ja.md` carry its upstream title, such as `@o3co/auth-provider-standalone`. When generating a scoped project, that title will not match your `package.json` name; edit it manually if it matters for your use case.
175
- - The template's README links into this repository with relative paths (`../../docs/…`, `../../packages/…`). Those resolve in the monorepo and not in a scaffolded project, where there is no `docs/` or `packages/` beside it; read them on GitHub instead.
176
-
177
- ## Generated Structure
178
-
179
- The generated project is a complete copy of the chosen template, such as
180
- [`templates/standalone`](../templates/standalone) (without `node_modules/` and
181
- `dist/`) plus `pnpm-workspace.yaml` (step 6) and, unless `--no-lockfile` was
182
- given or the lockfile step failed, `pnpm-lock.yaml` (step 7). The template's README describes its layout — which file is
183
- the composition, which is the host process, and what the scaffold owns.
184
-
185
- ## Programmatic API
186
-
187
- The module exports the functions the CLI is built from; their signatures are
188
- in [`src/index.mts`](src/index.mts).
189
-
190
- - `scaffold(targetDir, projectName, template?, options?)` — steps 4–6, from `template` (default `DEFAULT_TEMPLATE`, `"standalone"`); `options.noMfa` is `--no-mfa`. Throws, before writing anything, with `templateRefusal`'s message; and throws if a `workspace:*` dependency has no entry in `versions.json`.
191
- - `availableTemplates(templatesRoot?)` — the bundled templates' names, sorted.
192
- - `templateRefusal(template, templates)` — why `template` cannot be scaffolded (none bundled, or not one of them), or `undefined`.
193
- - `generateLockfile(targetDir)` — step 7. Returns `{ ok: true, command }` or `{ ok: false, reason }` rather than throwing.
194
- - `main()` — the CLI: reads `process.argv`, and exits non-zero on an invalid argument, an unknown template or an existing directory.
195
- - `isValidProjectName(name)` / `isValidDirName(name)` — the [Validation Rules](#validation-rules).
196
-
197
- ## See Also
198
-
199
- - [`templates/`](../templates) — The templates this tool generates from; [`@o3co/auth-provider-standalone`](../templates/standalone) is the default
200
- - [Composition templates ADR](../packages/core/docs/adr/2026-09-29-composition-templates.md) — Why the templates are split as they are
201
- - [`@o3co/auth-provider-core`](../packages/core) — Core application factory
5
+ Copyright 2026 1o1 Co. Ltd. Licensed under the Apache License, Version 2.0.
package/main.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { run } from "@o3co/auth-provider-scaffold/create-app";
3
+
4
+ process.exitCode = await run(process.argv.slice(2));
package/package.json CHANGED
@@ -1,41 +1,19 @@
1
1
  {
2
2
  "name": "@o3co/create-auth-provider",
3
- "version": "0.17.0-rc.4",
4
- "description": "Scaffold a new o3co/auth.provider project from one of its templates",
5
- "license": "Apache-2.0",
3
+ "version": "0.18.0-rc.1",
6
4
  "type": "module",
5
+ "license": "Apache-2.0",
7
6
  "repository": {
8
7
  "type": "git",
9
- "url": "https://github.com/o3co/auth.provider.git",
10
- "directory": "create-app"
11
- },
12
- "main": "./dist/index.mjs",
13
- "types": "./dist/index.d.mts",
14
- "exports": {
15
- ".": {
16
- "types": "./dist/index.d.mts",
17
- "import": "./dist/index.mjs"
18
- }
8
+ "url": "https://github.com/o3co/auth.provider"
19
9
  },
20
- "bin": {
21
- "create-auth-provider": "./dist/cli.mjs"
22
- },
23
- "files": [
24
- "dist",
25
- "templates"
26
- ],
27
10
  "engines": {
28
- "node": ">=22.0.0"
11
+ "node": ">=24"
29
12
  },
30
- "devDependencies": {
31
- "@o3co/ts.hocon": "^1.13.0",
32
- "@types/node": "^26.6.4",
33
- "typescript": "^6.0.3",
34
- "vitest": "^5.0.3"
13
+ "bin": {
14
+ "create-auth-provider": "./main.js"
35
15
  },
36
- "scripts": {
37
- "build": "tsc",
38
- "prebuild": "node scripts/copy-templates.mjs",
39
- "test": "vitest run"
16
+ "dependencies": {
17
+ "@o3co/auth-provider-scaffold": "0.18.0-rc.1"
40
18
  }
41
19
  }
package/README.ja.md DELETED
@@ -1,200 +0,0 @@
1
- # @o3co/create-auth-provider
2
-
3
- 最終更新: 2026-10-06
4
-
5
- auth.provider 用の CLI スキャフォルダーです。内包するテンプレートの 1 つから新しいサーバープロジェクトを生成します。
6
-
7
- ## 責務と役割
8
-
9
- **役割。** リポジトリ内の [`templates/`](../templates) にあるテンプレート
10
- (それぞれがデプロイ可能なコンポジションルート)の 1 つを、独立した新しい
11
- プロジェクトに変換する `npx` の入口です。運用者のマシン上で一度だけ実行されます。生成された
12
- プロジェクトはこのパッケージを import せず、このパッケージも `packages/*` の
13
- ライブラリを一切 import しません。
14
-
15
- **担うもの。** プロジェクト名・ディレクトリ名・テンプレート名の検証、選んだテンプレートのコピー、生成された
16
- `package.json` の書き換え(名前、`workspace:*` → 公開バージョン)、プロジェクトの
17
- `pnpm-workspace.yaml` の書き出し、そして一度きりの `pnpm-lock.yaml` の解決。
18
-
19
- **担わないもの。** 生成されるプロジェクトの中身 — ソース、設定、Dockerfile、
20
- テスト — はテンプレートのものです(このパッケージではなく `templates/<name>` を
21
- 編集してください)。どのテンプレートがあり、それぞれ何のためにあるかは
22
- [コンポジションテンプレートの ADR](../packages/core/docs/adr/2026-09-29-composition-templates.md)
23
- のものです。実行時の振る舞いは `@o3co/auth-provider-core` と、テンプレートが
24
- 依存するライブラリのものです。
25
-
26
- **別パッケージである理由。** `bin` 付きで単独公開されるため、provider をインストール
27
- せずに `npx` で実行できます。公開 tarball にはモノレポが含まれないので、このパッケージは
28
- すべてのテンプレートのコピーと、それらが固定するライブラリのバージョンを自前で持ちます
29
- ([テンプレートの同梱方法](#テンプレートの同梱方法))。
30
-
31
- ## 使い方
32
-
33
- ```bash
34
- npx @o3co/create-auth-provider <project-name> [--template <name>] [--dir <dir-name>] [--no-lockfile] [--no-mfa]
35
- ```
36
-
37
- `--template` はコピーするテンプレートを指定します(デフォルトは `standalone`)。
38
- テンプレートは [`templates/`](../templates) 配下で `package.json` を持つディレクトリ
39
- (シンボリックリンクでも、ドットで始まる名前でもないもの)で、それ以外の名前は、
40
- 使えるテンプレートの一覧を示して拒否されます。各テンプレートが
41
- 何のためにあるかはそれぞれの README に、テンプレートの分け方 — 機能ごとではなく
42
- コンポジションの形ごとに 1 つ — は
43
- [コンポジションテンプレートの ADR](../packages/core/docs/adr/2026-09-29-composition-templates.md) にあります。
44
-
45
- ```bash
46
- npx @o3co/create-auth-provider my-auth-server --template standalone
47
- ```
48
-
49
- `<project-name>` はスコープ付き npm 名 (`@scope/pkg`) とスコープなしの名前 (`pkg`) のどちらでも指定できます。
50
-
51
- スコープなしの例:
52
-
53
- ```bash
54
- npx @o3co/create-auth-provider my-auth-server
55
- cd my-auth-server
56
- pnpm install
57
- ```
58
-
59
- スコープ付きの例(ディレクトリ名はパッケージ部分 `auth.provider` がデフォルト):
60
-
61
- ```bash
62
- npx @o3co/create-auth-provider @my-org/auth.provider
63
- cd auth.provider
64
- pnpm install
65
- ```
66
-
67
- `--dir` でディレクトリ名を明示指定:
68
-
69
- ```bash
70
- npx @o3co/create-auth-provider @my-org/auth.provider --dir provider
71
- cd provider
72
- ```
73
-
74
- `--no-lockfile` を付けると lockfile の生成(下記の手順 7)を省略します。
75
-
76
- スキャフォールドは、すべてのパスワードログインに第二要素を求めます: テンプレートの
77
- MFA スイッチ `mfaMode`(`MFA_MODE`)のデフォルトは `required` です。development では
78
- ほかに何も要りません。それ以外では、MFA に要るもの(2 つのストアを Redis に、鍵、
79
- SMTP リレー)を設定するか、`MFA_MODE=off` で MFA を無効にするまで、
80
- プロジェクトの起動は拒否されます。MFA ページのデフォルトは `/mfa` で、プロジェクトが
81
- そこでページを用意しなければ、すべてのパスワードログインはそこで止まります。
82
- スイッチが何をインストールし、何を要するかはテンプレートの README にあります。
83
-
84
- `--no-mfa` を付けると、代わりにスイッチをスキャフォールド上で off と書きます。
85
- `config/application.conf` の末尾に `mfaMode = "off"` と
86
- `mfaMode = ${?MFA_MODE}` をこの順に追記するので、後のテンプレートがデフォルトを
87
- 変えてもプロジェクトは off のままで、`MFA_MODE` を設定すれば作り直さずに MFA を
88
- 有効にできます。MFA パッケージは依存に残り、ほかには何も削除・変更しません。
89
- プロジェクトに含まれるテスト(`pnpm run test`)はスイッチをプロジェクトの設定から
90
- 読み、その値が意味する動作を確かめるので、`--no-mfa` の有無にかかわらず通ります。
91
-
92
- 生成されるプロジェクトは pnpm のプロジェクトです。`Dockerfile` は
93
- `pnpm install --frozen-lockfile` でインストールし、ビルドの許可リストは
94
- `pnpm-workspace.yaml` にあります。
95
-
96
- CLI は最後のメッセージで次に `pnpm run debug` を実行するよう案内します。
97
- スキャフォールドのデフォルトのままでは、これは起動しません: `.env` ファイルは
98
- 読まず(読むのは compose ファイルだけ)、シェルの環境変数から issuer
99
- (`OAUTH_JWT_ISSUER`)、署名鍵のペア、セッションシークレット、ユーザーサービスの
100
- 2 つの URL(`REPOSITORIES_USER_HTTP_AUTHENTICATE_URL`、`REPOSITORIES_USER_HTTP_AUTHENTICATE_BY_TOKEN_URL`)、
101
- そして `localhost:6379` の Redis を必要とします。コマンドは、プロジェクトに含まれる
102
- テンプレートの README の[使い方](../templates/standalone/README.ja.md#使い方)にあります。
103
-
104
- ## 動作内容
105
-
106
- 1. `<project-name>` を検証する([バリデーションルール](#バリデーションルール) 参照)。
107
- 2. 生成先ディレクトリ名を決定する: `--dir <value>` が指定されていればその値、そうでなければスコープ付き名のパッケージ部分、最終的には入力値そのもの。
108
- 3. `--template`(デフォルト `standalone`)が内包するテンプレートの名前であることを確かめ、生成先ディレクトリを `<cwd>/<dir-name>` として解決し、すでに存在する場合はエラーで終了する。
109
- 4. 指定したテンプレートを生成先ディレクトリにコピーし(`node_modules/` と `dist/` は除外)、`.gitignore` を復元する(npm は公開パッケージから `.gitignore` という名前のファイルを落とすため、tarball には `gitignore` として入っている)。`--no-mfa` のときは、その `config/application.conf` に MFA スイッチの行を追記する。
110
- 5. 生成されたディレクトリの `package.json` を書き換える:
111
- - `name` を `<project-name>` そのままに設定する(スコープを保持)。
112
- - `"private": true` は意図的に残す: スキャフォールドされた ID プロバイダーが誤って公開できてはならないため。本当に公開するつもりなら自分でこのフィールドを削除する。
113
- - `dependencies`・`devDependencies`・`peerDependencies` の各 `workspace:*` を、内包する `versions.json` の `^<version>` に置き換える。
114
- 6. `bcrypt` 用の `onlyBuiltDependencies` 許可リストを書いた `pnpm-workspace.yaml` を生成する — pnpm 10.29 以降はこの許可リストを、単一パッケージのプロジェクトであってもこのファイルからしか読まない。
115
- 7. `--no-lockfile` が指定されていなければ、依存関係を `pnpm-lock.yaml` に解決する(`pnpm install --lockfile-only --ignore-workspace`。`pnpm` が `PATH` にない場合は `corepack pnpm` 経由)。到達可能なレジストリが必要で、失敗しても警告を出すだけでスキャフォールドは完了する。
116
- 8. 次のステップを出力する。
117
-
118
- ### 生成される `pnpm-lock.yaml`
119
-
120
- テンプレートの `Dockerfile` は `pnpm install --frozen-lockfile` でインストール
121
- するため、生成されたプロジェクトは lockfile がなければそもそもビルドできません。
122
- lockfile をテンプレートに同梱することはできません: 手順 5 がすべての
123
- `workspace:*` を公開バージョンに置き換えるまで、lockfile が固定すべき依存関係の
124
- 集合が存在しないからです。そこで、書き換え後の `package.json` に対してここで
125
- 一度だけ解決します。**コミットしてください** — `docker build` を再現可能にするのは
126
- この lockfile です。手順 7 が失敗した、または省略した場合は、プロジェクト内で一度
127
- `pnpm install` を実行して結果をコミットしてください。
128
-
129
- ## テンプレートの同梱方法
130
-
131
- パッケージの `prebuild` と `prepack` スクリプトが
132
- [`scripts/copy-templates.mjs`](scripts/copy-templates.mjs) を実行し、
133
- すべてのテンプレートを `create-app/templates/<name>` にコピーし(git 管理外。
134
- `node_modules/` と `dist/` は除外。コピー先は丸ごと作り直すので、リポジトリから
135
- 消したテンプレートは残らない)、`create-app/templates/versions.json` —
136
- 公開される `@o3co/auth-provider-*` 全パッケージの現在のバージョン — を書き出します。
137
- tarball には両方が入り(`files: ["dist", "templates"]`)、`scaffold()` はそこから
138
- 読みます。したがってスキャフォールドされるのは、このパッケージをビルドした時点の
139
- テンプレートで、同じビルド時点のライブラリバージョンに固定されます。
140
- テンプレートとは何か — `templates/` 配下のディレクトリで、シンボリックリンクでも
141
- ドットで始まる名前でもなく、`package.json` を持ち、小文字のケバブケースで名付けられた
142
- もの — は [`scripts/templates.mjs`](scripts/templates.mjs) の 1 か所で定義され、
143
- コピーと CI の全テンプレートのビルドの両方がそれを使います。スキャフォルダーの
144
- `availableTemplates()` は同じ規則でコピーを読みます。
145
- [`published-package.test.mts`](src/__tests__/published-package.test.mts) は
146
- パッケージを pack し、tarball がリポジトリのテンプレートをすべて含み、それぞれが
147
- そこからスキャフォールドできることを確かめます。
148
-
149
- CI は [`scripts/check-versions-json.mjs`](scripts/check-versions-json.mjs) を
150
- 実行します。`packages/` 配下の公開パッケージが `copy-templates.mjs` のバージョン
151
- 一覧に欠けているとき、または一覧がもう存在しないパッケージを挙げているときに
152
- 失敗します — そうでなければスキャフォールドがそのパッケージの `workspace:*` の
153
- バージョンを解決できずに失敗するためです。
154
-
155
- ## バリデーションルール
156
-
157
- `<project-name>` は以下のいずれかに一致する必要があります:
158
-
159
- - スコープなし: `^[a-z0-9][a-z0-9-._~]*$`
160
- - スコープ付き: `^@[a-z0-9][a-z0-9-._~]*/[a-z0-9][a-z0-9-._~]*$`
161
-
162
- いずれも空文字・`.`・`..` は不可、最大 214 文字。
163
-
164
- `--dir <value>` はスコープなしのパターンと同じ制約です。
165
-
166
- `--template <name>` は内包するテンプレートの名前と完全に一致する必要があります。パスは
167
- テンプレート名になりません。テンプレート名は小文字のケバブケース
168
- `^[a-z0-9]+(?:-[a-z0-9]+)*$`(英小文字と数字の並びを 1 つのハイフンでつなぐ)で、
169
- それ以外の名前のテンプレートはビルドが拒否します。
170
-
171
- ## 既知の制約
172
-
173
- - 内包されている各テンプレートの `README.md` / `README.ja.md` の見出しは上流の名前(たとえば `@o3co/auth-provider-standalone`)のままです。スコープ付きでプロジェクトを生成した場合、この見出しは `package.json` の名前と一致しません。必要に応じて手動で修正してください。
174
- - テンプレートの README は、このリポジトリ内を相対パス(`../../docs/…`、`../../packages/…`)でリンクしています。これはモノレポ内では解決しますが、横に `docs/` も `packages/` もないスキャフォールド先のプロジェクトでは解決しません。GitHub 上で参照してください。
175
-
176
- ## 生成される構造
177
-
178
- 生成されるプロジェクトは、選んだテンプレート(たとえば
179
- [`templates/standalone`](../templates/standalone))の完全なコピー(`node_modules/` と `dist/` を除く)に、`pnpm-workspace.yaml`(手順 6)と、
180
- `--no-lockfile` を指定せず lockfile の手順が失敗しなかった場合は `pnpm-lock.yaml`(手順 7)を加えたものです。どの
181
- ファイルがモジュール構成で、どれがホストプロセスで、スキャフォールドが何を
182
- 持つかは、テンプレートの README に記述されています。
183
-
184
- ## プログラマティック API
185
-
186
- モジュールは CLI を構成する関数を export しています。シグネチャは
187
- [`src/index.mts`](src/index.mts) にあります。
188
-
189
- - `scaffold(targetDir, projectName, template?, options?)` — 手順 4〜6。`template`(デフォルトは `DEFAULT_TEMPLATE` = `"standalone"`)からコピーする。`options.noMfa` は `--no-mfa` にあたる。コピーできないときは何も書かずに `templateRefusal` のメッセージで例外を投げる。`workspace:*` 依存が `versions.json` に見つからない場合も例外を投げる。
190
- - `availableTemplates(templatesRoot?)` — 内包するテンプレートの名前(ソート済み)。
191
- - `templateRefusal(template, templates)` — `template` からスキャフォールドできない理由(1 つも内包されていない、またはそのどれでもない)。できるときは `undefined`。
192
- - `generateLockfile(targetDir)` — 手順 7。例外を投げず、`{ ok: true, command }` か `{ ok: false, reason }` を返す。
193
- - `main()` — CLI 本体。`process.argv` を読み、不正な引数、未知のテンプレート、既存のディレクトリに対しては非ゼロで終了する。
194
- - `isValidProjectName(name)` / `isValidDirName(name)` — [バリデーションルール](#バリデーションルール)。
195
-
196
- ## 関連
197
-
198
- - [`templates/`](../templates) — このツールが生成元とするテンプレート。[`@o3co/auth-provider-standalone`](../templates/standalone) がデフォルト
199
- - [コンポジションテンプレートの ADR](../packages/core/docs/adr/2026-09-29-composition-templates.md) — テンプレートをこう分ける理由
200
- - [`@o3co/auth-provider-core`](../packages/core) — コアアプリケーションファクトリ
package/dist/cli.d.mts DELETED
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
3
- //# sourceMappingURL=cli.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.d.mts","sourceRoot":"","sources":["../src/cli.mts"],"names":[],"mappings":""}
package/dist/cli.mjs DELETED
@@ -1,18 +0,0 @@
1
- #!/usr/bin/env node
2
- /*
3
- * Copyright 2026 1o1 Co. Ltd.
4
- *
5
- * Licensed under the Apache License, Version 2.0 (the "License");
6
- * you may not use this file except in compliance with the License.
7
- * You may obtain a copy of the License at
8
- *
9
- * http://www.apache.org/licenses/LICENSE-2.0
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS IS" BASIS,
13
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- * See the License for the specific language governing permissions and
15
- * limitations under the License.
16
- */
17
- import { main } from "./index.mjs";
18
- main();
package/dist/index.d.mts DELETED
@@ -1,48 +0,0 @@
1
- /** The template a scaffold is made from when none is named. */
2
- export declare const DEFAULT_TEMPLATE = "standalone";
3
- /**
4
- * The templates under `templatesRoot`: every directory — not a symbolic link,
5
- * not dot-named — holding a `package.json`, sorted; none when the directory is
6
- * missing. This is the rule `scripts/templates.mjs` copies templates by, read
7
- * here from the copy, where `versions.json` sits beside them. A name is only
8
- * ever looked up in this list, so nothing outside the templates directory can
9
- * be named as a template.
10
- */
11
- export declare const availableTemplates: (templatesRoot?: string) => string[];
12
- /**
13
- * Why `template` cannot be scaffolded from `templates`, or `undefined` when it
14
- * can: none is bundled (a checkout that never ran the prebuild script), or it
15
- * is not one of them.
16
- */
17
- export declare const templateRefusal: (template: string, templates: readonly string[]) => string | undefined;
18
- export declare const isValidProjectName: (name: string) => boolean;
19
- export declare const isValidDirName: (name: string) => boolean;
20
- /** What `scaffold()` changes in the copy beyond the name and the versions. */
21
- export interface ScaffoldOptions {
22
- /**
23
- * Write the template's MFA switch off (`MFA_OFF_LINES`), so the scaffold
24
- * stays off whatever default a later template ships; `MFA_MODE` still
25
- * turns MFA on.
26
- */
27
- readonly noMfa?: boolean;
28
- }
29
- export declare const scaffold: (targetDir: string, projectName: string, template?: string, options?: ScaffoldOptions) => void;
30
- /** Outcome of the scaffold-time lockfile generation. */
31
- export type LockfileResult = {
32
- readonly ok: true;
33
- readonly command: string;
34
- } | {
35
- readonly ok: false;
36
- readonly reason: string;
37
- };
38
- /**
39
- * Resolve the scaffolded project's dependency graph into `pnpm-lock.yaml`,
40
- * which the template's `pnpm install --frozen-lockfile` build needs. The
41
- * lockfile cannot ship with the template: the dependency set it pins exists
42
- * only after `scaffold` has replaced every `workspace:*`. Best-effort (it needs
43
- * a package manager and a reachable registry), so failure is a result, not a
44
- * throw.
45
- */
46
- export declare const generateLockfile: (targetDir: string) => LockfileResult;
47
- export declare const main: () => void;
48
- //# sourceMappingURL=index.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.mts"],"names":[],"mappings":"AAgCA,+DAA+D;AAC/D,eAAO,MAAM,gBAAgB,eAAe,CAAC;AAE7C;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,GAAI,gBAAe,MAAuB,KAAG,MAAM,EAWjF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAC3B,UAAU,MAAM,EAChB,WAAW,SAAS,MAAM,EAAE,KAC1B,MAAM,GAAG,SAQX,CAAC;AAcF,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,KAAG,OAIjD,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,KAAG,OAI7C,CAAC;AAEF,8EAA8E;AAC9E,MAAM,WAAW,eAAe;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CACzB;AAeD,eAAO,MAAM,QAAQ,GACpB,WAAW,MAAM,EACjB,aAAa,MAAM,EACnB,WAAU,MAAyB,EACnC,UAAS,eAAoB,KAC3B,IAwEF,CAAC;AAEF,wDAAwD;AACxD,MAAM,MAAM,cAAc,GACvB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAkBnD;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAAI,WAAW,MAAM,KAAG,cA6BpD,CAAC;AA4EF,eAAO,MAAM,IAAI,QAAO,IA6EvB,CAAC"}