create-kumiko-app 0.4.150 → 0.4.151
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/feature-manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"source": "samples/apps/use-all-bundled APP_FEATURES (composeFeatures includeBundled)",
|
|
3
|
-
"featureCount":
|
|
2
|
+
"source": "samples/apps/use-all-bundled APP_FEATURES (composeFeatures includeBundled + signup)",
|
|
3
|
+
"featureCount": 59,
|
|
4
4
|
"features": [
|
|
5
5
|
{
|
|
6
6
|
"name": "admin-shell",
|
|
@@ -52,7 +52,8 @@
|
|
|
52
52
|
"toggleableDefault": null,
|
|
53
53
|
"requires": [
|
|
54
54
|
"user",
|
|
55
|
-
"tenant"
|
|
55
|
+
"tenant",
|
|
56
|
+
"delivery"
|
|
56
57
|
],
|
|
57
58
|
"optionalRequires": [],
|
|
58
59
|
"configReads": [],
|
|
@@ -64,7 +65,9 @@
|
|
|
64
65
|
"writeHandlers": [
|
|
65
66
|
"auth-email-password:write:change-password",
|
|
66
67
|
"auth-email-password:write:login",
|
|
67
|
-
"auth-email-password:write:logout"
|
|
68
|
+
"auth-email-password:write:logout",
|
|
69
|
+
"auth-email-password:write:signup-confirm",
|
|
70
|
+
"auth-email-password:write:signup-request"
|
|
68
71
|
],
|
|
69
72
|
"uiHints": {
|
|
70
73
|
"displayLabel": "Auth · Email + Password",
|
|
@@ -202,6 +205,20 @@
|
|
|
202
205
|
"secrets": [],
|
|
203
206
|
"writeHandlers": []
|
|
204
207
|
},
|
|
208
|
+
{
|
|
209
|
+
"name": "auth-self-registration",
|
|
210
|
+
"description": "Runtime on/off switch for the auth-email-password self-signup flow. Handler-less: composing it registers \"auth-self-registration\" as a toggleable feature (default ON). auth-email-password's signup-request handler and its `signupRegistrationStatus` query both read `ctx.hasFeature(\"auth-self-registration\")` — the query stays reachable when the toggle is off (deliberately not gated itself) so the public signup page can hide its own link/form. Only meaningful when `signup` is configured on `createAuthEmailPasswordFeature` — compose alongside it, then flip via the feature-toggles admin screen.",
|
|
211
|
+
"toggleableDefault": true,
|
|
212
|
+
"requires": [],
|
|
213
|
+
"optionalRequires": [],
|
|
214
|
+
"configReads": [],
|
|
215
|
+
"exposesApis": [],
|
|
216
|
+
"usesApis": [],
|
|
217
|
+
"extensionsUsed": [],
|
|
218
|
+
"configKeys": [],
|
|
219
|
+
"secrets": [],
|
|
220
|
+
"writeHandlers": []
|
|
221
|
+
},
|
|
205
222
|
{
|
|
206
223
|
"name": "billing-foundation",
|
|
207
224
|
"description": "Plugin host for subscription billing — manages the `read_subscriptions` projection table and exposes 5 domain events (subscription created/updated/canceled, invoice paid/failed) appended by the foundation's own `billing-foundation:write:process-event` write-handler after provider plugins verify and normalize each webhook. Also ships `billing-foundation:write:create-checkout-session` and `billing-foundation:write:create-portal-session` write-handlers, a `billing-foundation:query:subscription:list` query handler, and a `createSubscriptionWebhookHandler` factory for the `/api/subscription/webhook/:providerName` route. Low-level building block — use `subscription-stripe` or `subscription-mollie` unless you are writing a new payment provider.",
|
|
@@ -1442,7 +1459,7 @@
|
|
|
1442
1459
|
"uiHints": {
|
|
1443
1460
|
"displayLabel": "Personal Access Tokens",
|
|
1444
1461
|
"category": "identity",
|
|
1445
|
-
"recommended":
|
|
1462
|
+
"recommended": false
|
|
1446
1463
|
}
|
|
1447
1464
|
},
|
|
1448
1465
|
{
|
|
@@ -2141,6 +2158,81 @@
|
|
|
2141
2158
|
"recommended": false
|
|
2142
2159
|
}
|
|
2143
2160
|
},
|
|
2161
|
+
{
|
|
2162
|
+
"name": "tenant-settings",
|
|
2163
|
+
"description": "Per-tenant Currency + Locale defaults, exposed as two config keys (tenant-settings:config:currency, tenant-settings:config:locale) that surface in the self-populating Settings-Hub via `mask`. Pair with defineCreateWithTenantDefaults to auto-fill a money field's currency or a locale field on create instead of hard-coding a literal per entity.",
|
|
2164
|
+
"toggleableDefault": null,
|
|
2165
|
+
"requires": [
|
|
2166
|
+
"config"
|
|
2167
|
+
],
|
|
2168
|
+
"optionalRequires": [],
|
|
2169
|
+
"configReads": [],
|
|
2170
|
+
"exposesApis": [],
|
|
2171
|
+
"usesApis": [],
|
|
2172
|
+
"extensionsUsed": [],
|
|
2173
|
+
"configKeys": [
|
|
2174
|
+
{
|
|
2175
|
+
"key": "currency",
|
|
2176
|
+
"qualifiedName": "tenant-settings:config:currency",
|
|
2177
|
+
"type": "select",
|
|
2178
|
+
"scope": "tenant",
|
|
2179
|
+
"default": "EUR",
|
|
2180
|
+
"encrypted": false,
|
|
2181
|
+
"computed": false,
|
|
2182
|
+
"options": [
|
|
2183
|
+
"EUR",
|
|
2184
|
+
"USD",
|
|
2185
|
+
"GBP",
|
|
2186
|
+
"CHF",
|
|
2187
|
+
"JPY",
|
|
2188
|
+
"SEK",
|
|
2189
|
+
"NOK",
|
|
2190
|
+
"DKK",
|
|
2191
|
+
"PLN",
|
|
2192
|
+
"CZK",
|
|
2193
|
+
"CAD",
|
|
2194
|
+
"AUD",
|
|
2195
|
+
"NZD",
|
|
2196
|
+
"CNY",
|
|
2197
|
+
"INR"
|
|
2198
|
+
],
|
|
2199
|
+
"bounds": null,
|
|
2200
|
+
"pattern": null,
|
|
2201
|
+
"writeRoles": [
|
|
2202
|
+
"TenantAdmin",
|
|
2203
|
+
"Admin",
|
|
2204
|
+
"SystemAdmin"
|
|
2205
|
+
],
|
|
2206
|
+
"readRoles": [
|
|
2207
|
+
"all"
|
|
2208
|
+
]
|
|
2209
|
+
},
|
|
2210
|
+
{
|
|
2211
|
+
"key": "locale",
|
|
2212
|
+
"qualifiedName": "tenant-settings:config:locale",
|
|
2213
|
+
"type": "text",
|
|
2214
|
+
"scope": "tenant",
|
|
2215
|
+
"default": "en",
|
|
2216
|
+
"encrypted": false,
|
|
2217
|
+
"computed": false,
|
|
2218
|
+
"options": null,
|
|
2219
|
+
"bounds": null,
|
|
2220
|
+
"pattern": {
|
|
2221
|
+
"regex": "^[a-z]{2}(-[A-Z]{2})?$"
|
|
2222
|
+
},
|
|
2223
|
+
"writeRoles": [
|
|
2224
|
+
"TenantAdmin",
|
|
2225
|
+
"Admin",
|
|
2226
|
+
"SystemAdmin"
|
|
2227
|
+
],
|
|
2228
|
+
"readRoles": [
|
|
2229
|
+
"all"
|
|
2230
|
+
]
|
|
2231
|
+
}
|
|
2232
|
+
],
|
|
2233
|
+
"secrets": [],
|
|
2234
|
+
"writeHandlers": []
|
|
2235
|
+
},
|
|
2144
2236
|
{
|
|
2145
2237
|
"name": "text-content",
|
|
2146
2238
|
"description": "Generic Markdown text store keyed by `(tenantId, slug, lang)` — one row per combination in the `read_text_blocks` entity table. Provides `text-content:write:set` (TenantAdmin upsert) and `text-content:query:by-slug` (anonymous-capable read); use `SYSTEM_TENANT_ID` as the tenant for app-wide texts such as imprint, privacy policy, or FAQ. Other features (e.g. `legal-pages`) read blocks without a direct code import via the `createTextContentApi` / `requireTextContent` extraContext pattern.",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-kumiko-app",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.151",
|
|
4
4
|
"description": "`bun create kumiko-app <name>` — scaffold a new Kumiko app with an interactive feature picker.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
"vendor:manifest": "bun run scripts/vendor-manifest.ts"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@cosmicdrift/kumiko-dev-server": "
|
|
34
|
-
"@cosmicdrift/kumiko-framework": "
|
|
35
|
-
"@cosmicdrift/kumiko-server-runtime": "
|
|
33
|
+
"@cosmicdrift/kumiko-dev-server": "2.0.0",
|
|
34
|
+
"@cosmicdrift/kumiko-framework": "2.0.0",
|
|
35
|
+
"@cosmicdrift/kumiko-server-runtime": "2.0.0",
|
|
36
36
|
"@inquirer/core": "^10.0.0",
|
|
37
37
|
"@inquirer/prompts": "^7.4.0"
|
|
38
38
|
},
|
|
@@ -8,18 +8,24 @@
|
|
|
8
8
|
import { describe, expect, test } from "bun:test";
|
|
9
9
|
import { FEATURE_CONSTRUCTORS } from "../feature-constructors";
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
11
|
+
// Renders a value as hand-written TS source (unquoted object keys, quoted
|
|
12
|
+
// string values) instead of JSON — JSON.stringify(1) and JSON.stringify("1")
|
|
13
|
+
// both survive a whitespace+quote-strip compare as "1", which would hide a
|
|
14
|
+
// string/number divergence between callExpression and callArgs. Rendering
|
|
15
|
+
// like this and normalizing whitespace only keeps that divergence visible.
|
|
16
|
+
function renderTsLiteral(value: unknown): string {
|
|
17
|
+
if (Array.isArray(value)) return `[${value.map(renderTsLiteral).join(", ")}]`;
|
|
18
|
+
if (value !== null && typeof value === "object") {
|
|
19
|
+
const entries = Object.entries(value as Record<string, unknown>).map(
|
|
20
|
+
([key, val]) => `${key}: ${renderTsLiteral(val)}`,
|
|
21
|
+
);
|
|
22
|
+
return `{ ${entries.join(", ")} }`;
|
|
21
23
|
}
|
|
22
|
-
|
|
24
|
+
return JSON.stringify(value);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function expectedCallExpression(exportName: string, callArgs: readonly unknown[]): string {
|
|
28
|
+
const args = callArgs.map(renderTsLiteral).join(", ");
|
|
23
29
|
return `${exportName}(${args})`;
|
|
24
30
|
}
|
|
25
31
|
|
|
@@ -27,10 +33,10 @@ describe("FEATURE_CONSTRUCTORS callExpression/callArgs consistency", () => {
|
|
|
27
33
|
for (const [name, entry] of Object.entries(FEATURE_CONSTRUCTORS)) {
|
|
28
34
|
test(`${name}: callExpression matches exportName + callArgs`, () => {
|
|
29
35
|
if (entry.callArgs !== undefined) {
|
|
30
|
-
// callExpression is hand-formatted TS source
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
const normalize = (s: string) => s.replace(
|
|
36
|
+
// callExpression is hand-formatted TS source; compare with
|
|
37
|
+
// whitespace stripped only — NOT quotes, so a string arg ("1") vs.
|
|
38
|
+
// a number arg (1) still diverges after normalize.
|
|
39
|
+
const normalize = (s: string) => s.replace(/\s+/g, "");
|
|
34
40
|
expect(normalize(entry.callExpression)).toBe(
|
|
35
41
|
normalize(expectedCallExpression(entry.exportName, entry.callArgs)),
|
|
36
42
|
);
|
|
@@ -52,11 +52,9 @@ describe("--yes resolved set boots (issue-1174 regression)", () => {
|
|
|
52
52
|
});
|
|
53
53
|
|
|
54
54
|
test("the resolved --yes feature set boots without the GDPR PII-hook-coverage error", async () => {
|
|
55
|
-
// sessions (auto-included
|
|
56
|
-
//
|
|
57
|
-
|
|
58
|
-
// tokenVerifier boot invariant) is resolved into the set too.
|
|
59
|
-
expect(resolved.featureNames).toContain("personal-access-tokens");
|
|
55
|
+
// sessions (auto-included) pulls auth-foundation; #1570 allows zero
|
|
56
|
+
// tokenVerifier when sessionStore is mounted — PAT stays opt-in (#1514).
|
|
57
|
+
expect(resolved.featureNames).not.toContain("personal-access-tokens");
|
|
60
58
|
const instances = await instantiateResolved(resolved.featureNames);
|
|
61
59
|
const composed = composeFeatures(instances, { includeBundled: true });
|
|
62
60
|
expect(() => validateBoot(composed)).not.toThrow();
|
|
@@ -54,6 +54,14 @@ export const FEATURE_CONSTRUCTORS: Readonly<Record<string, ScaffoldFeatureEntry>
|
|
|
54
54
|
exportName: "createAuthEmailPasswordFeature",
|
|
55
55
|
callExpression: "createAuthEmailPasswordFeature()",
|
|
56
56
|
},
|
|
57
|
+
// Only meaningful alongside auth.signup — composeFeatures auto-mounts it
|
|
58
|
+
// when signup is set; listed so scaffolds can pick it explicitly (#1521).
|
|
59
|
+
"auth-self-registration": {
|
|
60
|
+
name: "auth-self-registration",
|
|
61
|
+
importPath: "@cosmicdrift/kumiko-bundled-features/auth-email-password",
|
|
62
|
+
exportName: "createAuthSelfRegistrationToggleFeature",
|
|
63
|
+
callExpression: "createAuthSelfRegistrationToggleFeature()",
|
|
64
|
+
},
|
|
57
65
|
"user-profile": {
|
|
58
66
|
name: "user-profile",
|
|
59
67
|
importPath: "@cosmicdrift/kumiko-bundled-features/user-profile",
|