Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/sv-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,4 @@ export { color } from './color.ts';

// Types
export type { Comments, AstTypes, SvelteAst } from './tooling/index.ts';
export type { TransformFn } from './tooling/transforms.ts';
34 changes: 17 additions & 17 deletions packages/sv-utils/src/tooling/transforms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import { type RootWithInstance, ensureScript } from './svelte/index.ts';
import * as svelteNs from './svelte/index.ts';
import * as textNs from './text.ts';

export type TransformFn = (content: string) => string;

type TransformOptions = {
/** Called when parsing fails. If provided, the original content is returned unchanged. */
onParseError?: (error: unknown) => void;
Expand Down Expand Up @@ -69,7 +71,7 @@ export const transforms = {
* Return `false` from the callback to abort - the original content is returned unchanged.
*/
script(
cb: (args: {
cb: (file: {
ast: TsEstree.Program;
comments: Comments;
content: string;
Expand All @@ -92,7 +94,7 @@ export const transforms = {
* Return `false` from the callback to abort - the original content is returned unchanged.
*/
svelte(
cb: (args: {
cb: (file: {
ast: SvelteAst.Root;
content: string;
svelte: typeof svelteNs;
Expand All @@ -119,14 +121,14 @@ export const transforms = {
*/
svelteScript(
scriptOptions: { language: 'ts' | 'js' },
cb: (args: {
cb: (file: {
ast: RootWithInstance;
content: string;
svelte: typeof svelteNs;
js: typeof jsNs;
}) => void | false,
options?: TransformOptions
): (content: string) => string {
): TransformFn {
return (content) => {
const parsed = withParseError(() => parseSvelte(content), options);
if (!parsed) return content;
Expand All @@ -148,13 +150,13 @@ export const transforms = {
* Return `false` from the callback to abort - the original content is returned unchanged.
*/
css(
cb: (args: {
cb: (file: {
ast: Omit<SvelteAst.CSS.StyleSheetBase, 'attributes' | 'content'>;
content: string;
css: typeof cssNs;
}) => void | false,
options?: TransformOptions
): (content: string) => string {
): TransformFn {
return (content) => {
const parsed = withParseError(() => parseCss(content), options);
if (!parsed) return content;
Expand All @@ -170,9 +172,9 @@ export const transforms = {
* Return `false` from the callback to abort - the original content is returned unchanged.
*/
json<T = any>(
cb: (args: { data: T; content: string; json: typeof jsonNs }) => void | false,
cb: (file: { data: T; content: string; json: typeof jsonNs }) => void | false,
options?: TransformOptions
): (content: string) => string {
): TransformFn {
return (content) => {
const parsed = withParseError(() => parseJson(content), options);
if (!parsed) return content;
Expand All @@ -188,9 +190,9 @@ export const transforms = {
* Return `false` from the callback to abort - the original content is returned unchanged.
*/
yaml(
cb: (args: { data: ReturnType<typeof parseYaml>['data']; content: string }) => void | false,
cb: (file: { data: ReturnType<typeof parseYaml>['data']; content: string }) => void | false,
options?: TransformOptions
): (content: string) => string {
): TransformFn {
return (content) => {
const parsed = withParseError(() => parseYaml(content), options);
if (!parsed) return content;
Expand All @@ -206,9 +208,9 @@ export const transforms = {
* Return `false` from the callback to abort - the original content is returned unchanged.
*/
toml(
cb: (args: { data: TomlTable; content: string }) => void | false,
cb: (file: { data: TomlTable; content: string }) => void | false,
options?: TransformOptions
): (content: string) => string {
): TransformFn {
return (content) => {
const parsed = withParseError(() => parseToml(content), options);
if (!parsed) return content;
Expand All @@ -224,9 +226,9 @@ export const transforms = {
* Return `false` from the callback to abort - the original content is returned unchanged.
*/
html(
cb: (args: { ast: SvelteAst.Fragment; content: string; html: typeof htmlNs }) => void | false,
cb: (file: { ast: SvelteAst.Fragment; content: string; html: typeof htmlNs }) => void | false,
options?: TransformOptions
): (content: string) => string {
): TransformFn {
return (content) => {
const parsed = withParseError(() => parseHtml(content), options);
if (!parsed) return content;
Expand All @@ -242,9 +244,7 @@ export const transforms = {
* Unlike other transforms there's no AST here - just string in, string out.
* Return the new content, or `false` to abort (original content is returned unchanged).
*/
text(
cb: (args: { content: string; text: typeof textNs }) => string | false
): (content: string) => string {
text(cb: (file: { content: string; text: typeof textNs }) => string | false): TransformFn {
return (content) => {
const result = cb({ content, text: textNs });
if (result === false) return content;
Expand Down
176 changes: 81 additions & 95 deletions packages/sv/src/addons/better-auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import {
Walker,
color,
dedent,
text,
transforms,
resolveCommand,
createPrinter
createPrinter,
type TransformFn
} from '@sveltejs/sv-utils';
import crypto from 'node:crypto';
import { defineAddon, defineAddonOptions } from '../core/config.ts';
Expand Down Expand Up @@ -86,14 +86,8 @@ export default defineAddon({
})
);

sv.file(
'.env',
transforms.text(({ content }) => generateEnvFileContent(content, demoGithub, false))
);
sv.file(
'.env.example',
transforms.text(({ content }) => generateEnvFileContent(content, demoGithub, true))
);
sv.file('.env', generateEnv(demoGithub, false));
sv.file('.env.example', generateEnv(demoGithub, true));

sv.file(
`${directory.lib}/server/auth.${language}`,
Expand Down Expand Up @@ -296,7 +290,7 @@ export default defineAddon({

sv.file(
`${directory.kitRoutes}/demo/better-auth/login/+page.server.${language}`,
transforms.text(({ content }) => {
(content) => {
if (content) {
const filePath = `${directory.kitRoutes}/demo/better-auth/login/+page.server.${language}`;
log.warn(`Existing ${color.warning(filePath)} file. Could not update.`);
Expand Down Expand Up @@ -397,31 +391,29 @@ export default defineAddon({
export const actions${ts(': Actions')} = {${signInEmailAction}${signInSocialAction}
};
`;
})
}
);

sv.file(
`${directory.kitRoutes}/demo/better-auth/login/+page.svelte`,
transforms.text(({ content }) => {
if (content) {
const filePath = `${directory.kitRoutes}/demo/better-auth/login/+page.svelte`;
log.warn(`Existing ${color.warning(filePath)} file. Could not update.`);
return false;
}
sv.file(`${directory.kitRoutes}/demo/better-auth/login/+page.svelte`, (content) => {
if (content) {
const filePath = `${directory.kitRoutes}/demo/better-auth/login/+page.svelte`;
log.warn(`Existing ${color.warning(filePath)} file. Could not update.`);
return false;
}

const tailwind = dependencyVersion('@tailwindcss/vite') !== undefined;
const input = tailwind
? ' class="mt-1 px-3 py-2 bg-white border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"'
: '';
const btn = tailwind
? ' class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 transition"'
: '';
const tailwind = dependencyVersion('@tailwindcss/vite') !== undefined;
const input = tailwind
? ' class="mt-1 px-3 py-2 bg-white border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"'
: '';
const btn = tailwind
? ' class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 transition"'
: '';

const svelte5 = !!dependencyVersion('svelte')?.startsWith('5');
const [ts, s5] = createPrinter(language === 'ts', svelte5);
const svelte5 = !!dependencyVersion('svelte')?.startsWith('5');
const [ts, s5] = createPrinter(language === 'ts', svelte5);

const passwordForm = demoPassword
? `
const passwordForm = demoPassword
? `
<form method="post" action="?/signInEmail" use:enhance>
<label>
Email
Expand All @@ -439,23 +431,23 @@ export default defineAddon({
<button formaction="?/signUpEmail"${btn}>Register</button>
</form>
${tailwind ? `<p class="text-red-500">{form?.message ?? ''}</p>` : `<p style="color: red">{form?.message ?? ''}</p>`}`
: '';
: '';

const separator =
demoPassword && demoGithub
? `\n\n\t\t\t\t\t<hr ${tailwind ? 'class="my-4"' : ''} />\n`
: '';
const separator =
demoPassword && demoGithub
? `\n\n\t\t\t\t\t<hr ${tailwind ? 'class="my-4"' : ''} />\n`
: '';

const githubForm = demoGithub
? `
const githubForm = demoGithub
? `
<form method="post" action="?/signInSocial" use:enhance>
<input type="hidden" name="provider" value="github" />
<input type="hidden" name="callbackURL" value="/demo/better-auth" />
<button${btn}>Sign in with GitHub</button>
</form>`
: '';
: '';

return dedent`
return dedent`
<script ${ts("lang='ts'")}>
import { enhance } from '$app/forms';
${ts("import type { ActionData } from './$types';\n")}
Expand All @@ -464,21 +456,18 @@ export default defineAddon({

<h1>Login</h1>${passwordForm}${separator}${githubForm}
`;
})
);
});

sv.file(
`${directory.kitRoutes}/demo/better-auth/+page.server.${language}`,
transforms.text(({ content }) => {
if (content) {
const filePath = `${directory.kitRoutes}/demo/better-auth/+page.server.${language}`;
log.warn(`Existing ${color.warning(filePath)} file. Could not update.`);
return false;
}
sv.file(`${directory.kitRoutes}/demo/better-auth/+page.server.${language}`, (content) => {
if (content) {
const filePath = `${directory.kitRoutes}/demo/better-auth/+page.server.${language}`;
log.warn(`Existing ${color.warning(filePath)} file. Could not update.`);
return false;
}

const [ts] = createPrinter(language === 'ts');
const d1AuthLine = d1 ? '\n\t\t\t\t\t\t\tconst { auth } = event.locals;\n' : '';
return dedent`
const [ts] = createPrinter(language === 'ts');
const d1AuthLine = d1 ? '\n\t\t\t\t\t\t\tconst { auth } = event.locals;\n' : '';
return dedent`
import { redirect } from '@sveltejs/kit';
${ts("import type { Actions } from './$types';")}
${ts("import type { PageServerLoad } from './$types';")}
Expand All @@ -500,25 +489,22 @@ export default defineAddon({
}
};
`;
})
);
});

sv.file(
`${directory.kitRoutes}/demo/better-auth/+page.svelte`,
transforms.text(({ content }) => {
if (content) {
const filePath = `${directory.kitRoutes}/demo/better-auth/+page.svelte`;
log.warn(`Existing ${color.warning(filePath)} file. Could not update.`);
return false;
}
sv.file(`${directory.kitRoutes}/demo/better-auth/+page.svelte`, (content) => {
if (content) {
const filePath = `${directory.kitRoutes}/demo/better-auth/+page.svelte`;
log.warn(`Existing ${color.warning(filePath)} file. Could not update.`);
return false;
}

const tailwind = dependencyVersion('@tailwindcss/vite') !== undefined;
const twBtnClasses =
'class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 transition"';
const tailwind = dependencyVersion('@tailwindcss/vite') !== undefined;
const twBtnClasses =
'class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 transition"';

const svelte5 = !!dependencyVersion('svelte')?.startsWith('5');
const [ts, s5] = createPrinter(language === 'ts', svelte5);
return dedent`
const svelte5 = !!dependencyVersion('svelte')?.startsWith('5');
const [ts, s5] = createPrinter(language === 'ts', svelte5);
return dedent`
<script ${ts("lang='ts'")}>
import { enhance } from '$app/forms';
${ts("import type { PageServerData } from './$types';\n")}
Expand All @@ -531,8 +517,7 @@ export default defineAddon({
<button ${tailwind ? twBtnClasses : ''}>Sign out</button>
</form>
`;
})
);
});
}
},

Expand All @@ -558,29 +543,30 @@ export default defineAddon({
return steps;
}
});

function generateEnvFileContent(content: string, demoGithub: boolean, isExample: boolean) {
content = text.upsert(content, 'ORIGIN', {
value: isExample ? `""` : `"http://localhost:5173"`,
separator: true
});
content = text.upsert(content, 'BETTER_AUTH_SECRET', {
value: isExample ? `""` : `"${crypto.randomUUID()}"`,
comment: [
'Better Auth',
'For production use 32 characters and generated with high entropy',
'https://www.better-auth.com/docs/installation'
],
separator: true
});

if (demoGithub) {
content = text.upsert(content, 'GITHUB_CLIENT_ID', {
value: `""`,
comment: 'GitHub OAuth\n# https://www.better-auth.com/docs/authentication/github'
type GenerateEnv = (demoGithub: boolean, isExample: boolean) => TransformFn;
const generateEnv: GenerateEnv = (demoGithub, isExample) =>
transforms.text(({ content, text }) => {
content = text.upsert(content, 'ORIGIN', {
value: isExample ? `""` : `"http://localhost:5173"`,
separator: true
});
content = text.upsert(content, 'BETTER_AUTH_SECRET', {
value: isExample ? `""` : `"${crypto.randomUUID()}"`,
comment: [
'Better Auth',
'For production use 32 characters and generated with high entropy',
'https://www.better-auth.com/docs/installation'
],
separator: true
});
content = text.upsert(content, 'GITHUB_CLIENT_SECRET', { value: `""` });
}

return content;
}
if (demoGithub) {
content = text.upsert(content, 'GITHUB_CLIENT_ID', {
value: `""`,
comment: 'GitHub OAuth\n# https://www.better-auth.com/docs/authentication/github'
});
content = text.upsert(content, 'GITHUB_CLIENT_SECRET', { value: `""` });
}

return content;
});
Loading
Loading