create-ailk 0.31.0 → 0.33.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.md +50 -8
- package/component-catalog.json +12 -1
- package/component-catalog.md +6 -5
- package/dist/body-heading.d.ts +13 -0
- package/dist/body-heading.js +19 -5
- package/dist/cutover.d.ts +6 -1
- package/dist/cutover.js +23 -6
- package/dist/export-content.d.ts +6 -3
- package/dist/export-content.js +79 -10
- package/dist/language-import.d.ts +16 -3
- package/dist/language-import.js +27 -11
- package/dist/lib/import-mdx.d.ts +42 -0
- package/dist/lib/import-mdx.js +584 -65
- package/dist/lib/render-comparison.d.ts +51 -0
- package/dist/lib/render-comparison.js +205 -6
- package/dist/mdx-braces.d.ts +73 -0
- package/dist/mdx-braces.js +285 -0
- package/dist/migrate-content.d.ts +1 -1
- package/dist/migrate-content.js +4 -2
- package/dist/programmatic.js +2 -8
- package/dist/seed-flows.d.ts +1 -1
- package/dist/seed-flows.js +9 -4
- package/dist/site-manifest.js +6 -38
- package/dist/site-roster.d.ts +46 -3
- package/dist/site-roster.js +124 -4
- package/dist/surfaces.d.ts +8 -0
- package/dist/surfaces.js +17 -0
- package/dist/update.d.ts +21 -1
- package/dist/update.js +142 -11
- package/package.json +3 -3
- package/templates/.github/workflows/ci.yml +2 -0
- package/templates/apps/api/CLAUDE.md +7 -5
- package/templates/apps/api/src/lib/__mocks__/prisma.ts +13 -0
- package/templates/apps/mcp/.env.example +7 -1
- package/templates/apps/web/__tests__/setup.ts +9 -0
- package/templates/apps/web/app/[locale]/(auth)/__tests__/password-reset.test.tsx +28 -0
- package/templates/apps/web/app/[locale]/(auth)/verify-email/__tests__/actions.test.ts +94 -0
- package/templates/apps/web/app/[locale]/(auth)/verify-email/actions.ts +77 -0
- package/templates/apps/web/app/[locale]/(auth)/verify-email/page.tsx +79 -14
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/hub-mode.test.tsx +7 -0
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/new-menu.test.tsx +7 -0
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/page.test.tsx +7 -0
- package/templates/apps/web/app/[locale]/[slug]/[detail]/__tests__/page.test.tsx +3 -0
- package/templates/apps/web/app/[locale]/[slug]/__tests__/page.test.tsx +3 -0
- package/templates/apps/web/app/[locale]/about/__tests__/about-routes.test.tsx +3 -0
- package/templates/apps/web/app/[locale]/careers/__tests__/page-renderer-migration.test.tsx +3 -0
- package/templates/apps/web/app/[locale]/contact/__tests__/contact.actions.test.ts +21 -0
- package/templates/apps/web/app/[locale]/contact/contact.actions.ts +15 -9
- package/templates/apps/web/app/[locale]/flows/[slug]/FlowStepperClient.tsx +38 -105
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/FlowStepperClient.invite.test.tsx +72 -58
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/verify.test.tsx +249 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/ResultsClient.tsx +164 -20
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/__tests__/by-result.test.tsx +269 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/__tests__/score.test.tsx +179 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/page.tsx +108 -40
- package/templates/apps/web/app/[locale]/flows/[slug]/verify/page.tsx +153 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/verify.actions.ts +151 -0
- package/templates/apps/web/app/[locale]/meet/confirmed/BookingHandOff.tsx +1 -1
- package/templates/apps/web/app/[locale]/pricing/[slug]/__tests__/page.test.tsx +3 -0
- package/templates/apps/web/app/[locale]/pricing/__tests__/offerings.test.tsx +3 -0
- package/templates/apps/web/app/[locale]/pricing/__tests__/page.test.tsx +3 -0
- package/templates/apps/web/app/[locale]/pricing/__tests__/unconnected.test.tsx +3 -0
- package/templates/apps/web/app/[locale]/projects/__tests__/page-renderer-migration.test.tsx +3 -0
- package/templates/apps/web/app/[locale]/services/__tests__/page-renderer-migration.test.tsx +3 -0
- package/templates/apps/web/app/[locale]/team/__tests__/team-routes.test.tsx +3 -0
- package/templates/apps/web/app/[locale]/thanks/[slug]/__tests__/page.test.tsx +3 -20
- package/templates/apps/web/app/[locale]/thanks/[slug]/page.tsx +2 -9
- package/templates/apps/web/auth.ts +22 -6
- package/templates/apps/web/lib/__tests__/account-config.test.ts +69 -0
- package/templates/apps/web/lib/__tests__/auth-email.test.ts +99 -1
- package/templates/apps/web/lib/__tests__/page-chrome.test.ts +3 -0
- package/templates/apps/web/lib/__tests__/structured-data.test.tsx +134 -10
- package/templates/apps/web/lib/__tests__/telemetry-scrub.test.ts +20 -0
- package/templates/apps/web/lib/account-config.ts +52 -14
- package/templates/apps/web/lib/auth-email.ts +87 -5
- package/templates/apps/web/lib/telemetry-scrub.ts +6 -0
- package/templates/apps/web/messages/en.json +26 -1
- package/templates/apps/web/src/lib/routes.ts +5 -3
- package/templates/database/seed.ts +7 -7
- package/templates/package.json +2 -1
- package/templates/tools/body-heading.ts +440 -0
- package/templates/tools/check-mdx-body.ts +123 -0
- package/templates/tools/mdx-braces.ts +303 -0
- package/versions.json +48 -48
- package/templates/apps/web/app/[locale]/thanks/[slug]/AccountInviteLink.tsx +0 -89
- package/templates/apps/web/app/[locale]/thanks/[slug]/__tests__/AccountInviteLink.test.tsx +0 -104
package/dist/language-import.js
CHANGED
|
@@ -88,7 +88,7 @@ function entriesOf(section) {
|
|
|
88
88
|
if (!str(raw["question"]) || !str(raw["answer"]))
|
|
89
89
|
return undefined;
|
|
90
90
|
entries.push({
|
|
91
|
-
key: raw["question"],
|
|
91
|
+
key: JSON.stringify([raw["question"], raw["answer"]]),
|
|
92
92
|
words: { question: raw["question"], answer: raw["answer"] },
|
|
93
93
|
kicker: raw["kicker"] !== undefined,
|
|
94
94
|
});
|
|
@@ -113,12 +113,13 @@ export function withLanguage(adapters, options) {
|
|
|
113
113
|
let state = "unprobed";
|
|
114
114
|
let offStatus;
|
|
115
115
|
const items = new Map();
|
|
116
|
-
/** In-run FAQ slug claims, so two
|
|
116
|
+
/** In-run FAQ slug claims, so two items never share a slug (D2, #10778 D2); a term's slug is its key. */
|
|
117
117
|
const claimed = new Map();
|
|
118
118
|
const occurrences = [];
|
|
119
119
|
const homes = [];
|
|
120
120
|
const kickers = [];
|
|
121
121
|
const displaced = [];
|
|
122
|
+
const collisions = [];
|
|
122
123
|
async function call(method, url, body) {
|
|
123
124
|
for (let retry = 0;; retry++) {
|
|
124
125
|
let response;
|
|
@@ -208,9 +209,11 @@ export function withLanguage(adapters, options) {
|
|
|
208
209
|
throw new Error(`language: ${kind}/${known.slug}: ${known.failed}`);
|
|
209
210
|
if (home && !known.winner.home) {
|
|
210
211
|
// D3 — the home page outranks a page read before it; an item this run
|
|
211
|
-
// created takes its words
|
|
212
|
+
// created takes its words unless they are already its own (#10778 D4),
|
|
213
|
+
// and a found one is never written (D4).
|
|
214
|
+
const rewords = known.created && options.apply && !same(known.winner.words, entry.words);
|
|
212
215
|
known.winner = { page, words: entry.words, home: true };
|
|
213
|
-
if (
|
|
216
|
+
if (rewords)
|
|
214
217
|
await write(known, entry.words, known.version ?? null);
|
|
215
218
|
}
|
|
216
219
|
return known;
|
|
@@ -221,15 +224,22 @@ export function withLanguage(adapters, options) {
|
|
|
221
224
|
stored = await read(kind, slug);
|
|
222
225
|
}
|
|
223
226
|
else {
|
|
224
|
-
const
|
|
227
|
+
const question = entry.words["question"];
|
|
228
|
+
const first = faqSlug(question);
|
|
225
229
|
let skipped;
|
|
230
|
+
let collided;
|
|
226
231
|
for (let n = 1;; n++) {
|
|
227
232
|
const candidate = n === 1 ? first : `${first}-${n}`;
|
|
233
|
+
// Claimed in this run by another pair: the same question answered otherwise
|
|
234
|
+
// is a collision (#10778 D2), another question that slugs alike is not.
|
|
228
235
|
const holder = claimed.get(candidate);
|
|
229
|
-
if (holder !== undefined
|
|
236
|
+
if (holder !== undefined) {
|
|
237
|
+
if (holder.winner.words["question"] === question)
|
|
238
|
+
collided ??= { slug: candidate, from: holder.winner.page };
|
|
230
239
|
continue;
|
|
240
|
+
}
|
|
231
241
|
stored = await read(kind, candidate);
|
|
232
|
-
if (stored !== null && stored.words["question"] !==
|
|
242
|
+
if (stored !== null && stored.words["question"] !== question) {
|
|
233
243
|
skipped ??= candidate;
|
|
234
244
|
continue;
|
|
235
245
|
}
|
|
@@ -238,9 +248,9 @@ export function withLanguage(adapters, options) {
|
|
|
238
248
|
}
|
|
239
249
|
if (skipped !== undefined)
|
|
240
250
|
displaced.push({ slug: skipped, next: slug });
|
|
251
|
+
if (collided !== undefined)
|
|
252
|
+
collisions.push({ ...collided, page, next: slug });
|
|
241
253
|
}
|
|
242
|
-
if (kind === "faq")
|
|
243
|
-
claimed.set(slug, entry.key);
|
|
244
254
|
const item = {
|
|
245
255
|
kind,
|
|
246
256
|
slug,
|
|
@@ -249,6 +259,8 @@ export function withLanguage(adapters, options) {
|
|
|
249
259
|
...(stored !== null && { stored }),
|
|
250
260
|
};
|
|
251
261
|
items.set(mapKey, item);
|
|
262
|
+
if (kind === "faq")
|
|
263
|
+
claimed.set(slug, item);
|
|
252
264
|
if (stored === null)
|
|
253
265
|
await write(item, entry.words, null);
|
|
254
266
|
return item;
|
|
@@ -355,7 +367,9 @@ export function withLanguage(adapters, options) {
|
|
|
355
367
|
const key = `${PREFIX[item.kind]}${item.slug}`;
|
|
356
368
|
const live = item.created || item.stored.live;
|
|
357
369
|
if (item.kind === home.kind && item.failed === undefined && live && !home.shown.has(key)) {
|
|
358
|
-
|
|
370
|
+
const shown = item.created ? item.winner.words : (item.stored.published ?? {});
|
|
371
|
+
const name = shown[item.kind === "faq" ? "question" : "term"] ?? "";
|
|
372
|
+
topUps.push({ kind: item.kind, slug: item.slug, page: `/${home.slug}`, name });
|
|
359
373
|
}
|
|
360
374
|
}
|
|
361
375
|
}
|
|
@@ -371,6 +385,7 @@ export function withLanguage(adapters, options) {
|
|
|
371
385
|
topUps,
|
|
372
386
|
droppedKickers: kickers,
|
|
373
387
|
displaced,
|
|
388
|
+
collisions,
|
|
374
389
|
};
|
|
375
390
|
}
|
|
376
391
|
return {
|
|
@@ -421,13 +436,14 @@ export function languageCountsLine(result, apply) {
|
|
|
421
436
|
const { created, unchanged, kept, failed } = result.counts;
|
|
422
437
|
return `language: ${apply ? "created" : "create"} ${created} · unchanged ${unchanged} · kept ${kept} · failed ${failed}`;
|
|
423
438
|
}
|
|
424
|
-
/** Every line D7 prints, in order: items, counts, render changes, top-ups, dropped kickers, displacements. */
|
|
439
|
+
/** Every line D7 prints, in order: items, counts, render changes, collisions, top-ups, dropped kickers, displacements. */
|
|
425
440
|
export function languageLines(result, apply) {
|
|
426
441
|
const verb = (r) => (!apply && r === "created" ? "create" : r);
|
|
427
442
|
return [
|
|
428
443
|
...result.items.map((i) => `language: ${i.kind}/${i.slug}: ${verb(i.result)}${i.reason === undefined ? "" : ` — ${i.reason}`}`),
|
|
429
444
|
languageCountsLine(result, apply),
|
|
430
445
|
...result.renderChanges.map(renderChangeLine),
|
|
446
|
+
...result.collisions.map((c) => `language: faq/${c.slug} on ${c.page}: not merged — ${c.from} answers the same question otherwise; ${c.page} pins faq/${c.next}`),
|
|
431
447
|
...result.topUps.map((t) => `language: ${t.kind}/${t.slug}: now also on ${t.page}`),
|
|
432
448
|
...result.droppedKickers.map((k) => `language: faq/${k.slug}: kicker dropped`),
|
|
433
449
|
...result.displaced.map((d) => `language: faq/${d.slug}: the workspace holds a different question here; the file's is ${d.next}`),
|
package/dist/lib/import-mdx.d.ts
CHANGED
|
@@ -32,6 +32,19 @@ export interface MdxAdapterModule {
|
|
|
32
32
|
data: Record<string, unknown>;
|
|
33
33
|
content: string;
|
|
34
34
|
};
|
|
35
|
+
/**
|
|
36
|
+
* The site-field rule from the adapter's validation package (#10806 D4);
|
|
37
|
+
* without it the editorial walk sends no `siteFields` and no `tags`, and
|
|
38
|
+
* names the keys it would have sent.
|
|
39
|
+
*/
|
|
40
|
+
siteFields?: SiteFieldRules;
|
|
41
|
+
}
|
|
42
|
+
/** The validation package's site-field rule, typed structurally. */
|
|
43
|
+
export interface SiteFieldRules {
|
|
44
|
+
refusal: (key: string, value: unknown) => string | null;
|
|
45
|
+
publicPageTags: (tags: readonly unknown[]) => string[];
|
|
46
|
+
maxKeys: number;
|
|
47
|
+
maxBytes: number;
|
|
35
48
|
}
|
|
36
49
|
export interface ImportMdxOptions {
|
|
37
50
|
/** The site's content root (`content/`). */
|
|
@@ -88,6 +101,35 @@ interface At {
|
|
|
88
101
|
export declare function outcomePath(at: At): string;
|
|
89
102
|
/** The whole report, one line per page and a final count line. */
|
|
90
103
|
export declare function formatImportMdxReport(result: ImportMdxResult): string;
|
|
104
|
+
/**
|
|
105
|
+
* A section string's inline HTML as the constrained Markdown the upstream
|
|
106
|
+
* renderers read (#10804 D3): a link with an allowed href becomes
|
|
107
|
+
* `[label](href)`, `<br>` a newline, a block or list item a paragraph break,
|
|
108
|
+
* and every other tag goes, its text kept. A string with no tag comes back
|
|
109
|
+
* byte-identical; the result never holds one. `notCarried` names, sorted,
|
|
110
|
+
* every tag the layout does not keep.
|
|
111
|
+
*/
|
|
112
|
+
export declare function inlineHtmlToMarkdown(value: string): {
|
|
113
|
+
text: string;
|
|
114
|
+
notCarried: string[];
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Each section with every string in its `data` that holds a tag converted by
|
|
118
|
+
* `inlineHtmlToMarkdown` (#10804 D2); keys and tag-free strings are kept as
|
|
119
|
+
* they are. `notCarried` is the sorted union of the names it did not carry.
|
|
120
|
+
*/
|
|
121
|
+
export declare function sectionsWithoutHtml<T>(sections: readonly T[]): {
|
|
122
|
+
sections: T[];
|
|
123
|
+
notCarried: string[];
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* The first section-string or key rule of the hub's structure write
|
|
127
|
+
* (`checkSectionData`) the layout breaks, as `<message> (sections[i].data<path>)`,
|
|
128
|
+
* or `undefined` (#10804 D5). The depth and size bounds are not restated.
|
|
129
|
+
*/
|
|
130
|
+
export declare function layoutRefusal(layout: {
|
|
131
|
+
sections: readonly unknown[];
|
|
132
|
+
}): string | undefined;
|
|
91
133
|
export declare function importMdx(opts: ImportMdxOptions): Promise<ImportMdxResult>;
|
|
92
134
|
/**
|
|
93
135
|
* The site's installed adapter package, resolved from its `apps/web` — never
|