Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: supabase #45

Merged
merged 79 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
6ece58c
add baas category
mstibbard Sep 2, 2024
1090ebd
init attempt
mstibbard Sep 2, 2024
a70bc62
helper script option
mstibbard Sep 2, 2024
17f5e0b
admin option. refactor setting env vars
mstibbard Sep 2, 2024
7398d39
update next steps
mstibbard Sep 2, 2024
f9e6353
demo option
mstibbard Sep 2, 2024
0312470
Apply suggestions from benmccann and manuel3108
mstibbard Sep 3, 2024
48008a9
actioning a missed suggestion from benmccann
mstibbard Sep 3, 2024
dab765f
remove baas category
mstibbard Sep 3, 2024
777b3ee
add packageManager to nextSteps data object
mstibbard Sep 3, 2024
85153cb
caps reverted somehow
mstibbard Sep 3, 2024
ec79552
add script execution step between packages and files steps
mstibbard Sep 4, 2024
3473f14
update config.toml and email template. improve demo
mstibbard Sep 4, 2024
13a5c60
adder.scripts optional
mstibbard Sep 4, 2024
6fd7e0c
more experimenting
mstibbard Sep 4, 2024
4fc52f0
revert script execution experiment
mstibbard Sep 4, 2024
5ce1f9c
better script experiment
mstibbard Sep 5, 2024
40f9484
multiselect auth option: basic, magic link, oauth. better nextSteps
mstibbard Sep 5, 2024
3782f34
fix next steps indenting
mstibbard Sep 5, 2024
c44e7dc
use execute commands instead of installing deps
mstibbard Sep 6, 2024
6769375
made conditionals names consistent
mstibbard Sep 6, 2024
175dc53
add password reset for basic auth. fix supabase cli vscode setting gen
mstibbard Sep 6, 2024
b08123c
add local google oauth. move oauth server-side
mstibbard Sep 7, 2024
aba58ac
add changeset
mstibbard Sep 12, 2024
1365d0f
fix unused imports
mstibbard Sep 12, 2024
902383a
move supabase adder
manuel3108 Sep 27, 2024
9e098bd
use `@svelte-cli/core` and formatting
manuel3108 Sep 27, 2024
f66e348
fix most important merge conflicts
manuel3108 Sep 28, 2024
f041ba8
update adder
manuel3108 Sep 28, 2024
5cd1bff
re-add scripts in correct place
manuel3108 Sep 28, 2024
d53dd78
make supabase adder work
manuel3108 Sep 28, 2024
91e6b91
remove external integration type and uses scripts instead
manuel3108 Sep 28, 2024
8ca5a20
fix linting
manuel3108 Sep 28, 2024
c2ba9c5
avoid "Need to install the following packages:" message if using npx
manuel3108 Sep 29, 2024
657a44f
implement first review feedback
manuel3108 Sep 30, 2024
0057e25
fix categories
manuel3108 Oct 2, 2024
238971d
Merge branch 'main' into feat/supabase
manuel3108 Oct 2, 2024
527f29f
fix errors
manuel3108 Oct 2, 2024
6d0be37
fix indendation
manuel3108 Oct 2, 2024
7a4e70a
use svelte 5 syntax
manuel3108 Oct 2, 2024
2113a7d
fix lucia adder
manuel3108 Oct 2, 2024
ffe9793
remove oauth option
manuel3108 Oct 2, 2024
1492947
temp
manuel3108 Oct 3, 2024
7514f24
Improve `app.d.ts` robustnes
manuel3108 Oct 3, 2024
07137d7
Merge branch 'main' into feat/supabase
manuel3108 Oct 3, 2024
00f06f7
make `+layout.ts` more robust
manuel3108 Oct 3, 2024
bd5f1e9
Make `+layout.server.ts` more robust
manuel3108 Oct 3, 2024
5f24341
improve robustnes for common files
manuel3108 Oct 3, 2024
5722235
make `+hooks.server.ts` more robust
manuel3108 Oct 3, 2024
0af1308
fix duplicated handle import
manuel3108 Oct 3, 2024
21b16fc
add missing type
manuel3108 Oct 3, 2024
e7fb9a0
Merge branch 'main' into feat/supabase
manuel3108 Oct 6, 2024
a5d4d61
fix merge issues
manuel3108 Oct 6, 2024
40a073b
fix arg parsing
manuel3108 Oct 6, 2024
0335131
fix merge issue
manuel3108 Oct 6, 2024
426ae51
word
AdrianGonz97 Oct 6, 2024
9d8a85f
simplify script execution
AdrianGonz97 Oct 6, 2024
65b0bde
dedent
AdrianGonz97 Oct 6, 2024
e0a0e21
more tweaks
AdrianGonz97 Oct 6, 2024
e4b863c
simplify
AdrianGonz97 Oct 6, 2024
5ea4e0f
no changesets yet
AdrianGonz97 Oct 6, 2024
fa54fc1
simplify
AdrianGonz97 Oct 6, 2024
fd794d3
update pm detector
AdrianGonz97 Oct 6, 2024
d463b28
simplify app namespace
AdrianGonz97 Oct 6, 2024
d8bf2a0
provide highlighter for consistent `nextSteps`
AdrianGonz97 Oct 6, 2024
f10f94e
cache packageManager
AdrianGonz97 Oct 6, 2024
70e03ca
tweaks
AdrianGonz97 Oct 6, 2024
d01c77f
simplify further
AdrianGonz97 Oct 6, 2024
c4f2fa1
a few nits
AdrianGonz97 Oct 7, 2024
b857da9
tab tweaks
AdrianGonz97 Oct 7, 2024
d490afd
extract demos
manuel3108 Oct 7, 2024
0010510
extract helpers
manuel3108 Oct 7, 2024
3d689cd
simplify
AdrianGonz97 Oct 7, 2024
ce115f4
Make children in layout non optional
manuel3108 Oct 8, 2024
74d4ae6
remove ternaries
AdrianGonz97 Oct 8, 2024
d4fa542
upgrade package-manager-detector to sync version
benmccann Oct 9, 2024
54d13d2
remove supabase adder
manuel3108 Oct 9, 2024
7615171
fix lint?
manuel3108 Oct 9, 2024
045b1fb
update detect pm in cli as well
AdrianGonz97 Oct 9, 2024
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: 0 additions & 1 deletion community-adder-template/src/config/adder.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ export const adder = defineAdderConfig({
environments: { kit: true, svelte: true }
},
options,
integrationType: 'inline',
packages: [],
files: [
{
Expand Down
302 changes: 300 additions & 2 deletions packages/adders/common.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import { imports, exports, common } from '@svelte-cli/core/js';
import type { ScriptFileEditor } from '@svelte-cli/core';
import { imports, exports, common, variables, functions } from '@svelte-cli/core/js';
import { Walker, type AstKinds, type AstTypes, type ScriptFileEditor } from '@svelte-cli/core';
import type { Question } from '@svelte-cli/core/internal';

export function createPrinter(...conditions: boolean[]) {
const printers = conditions.map((condition) => {
return (content: string, alt = '') => (condition ? content : alt);
});
return printers;
}

export function addEslintConfigPrettier({ ast }: ScriptFileEditor<Record<string, Question>>) {
// if a default import for `eslint-plugin-svelte` already exists, then we'll use their specifier's name instead
const importNodes = ast.body.filter((n) => n.type === 'ImportDeclaration');
Expand Down Expand Up @@ -57,3 +64,294 @@ export function addEslintConfigPrettier({ ast }: ScriptFileEditor<Record<string,
array.elements.push(...nodesToInsert);
}
}

export function addGlobalAppInterface(
ast: AstTypes.Program,
name: 'Error' | 'Locals' | 'PageData' | 'PageState' | 'Platform'
) {
let globalDecl = ast.body
.filter((n) => n.type === 'TSModuleDeclaration')
.find((m) => m.global && m.declare);

if (!globalDecl) {
globalDecl = common.statementFromString('declare global {}') as AstTypes.TSModuleDeclaration;
ast.body.push(globalDecl);
}

if (globalDecl.body?.type !== 'TSModuleBlock') {
throw new Error('Unexpected body type of `declare global` in `src/app.d.ts`');
}

let app: AstTypes.TSModuleDeclaration | undefined;
let interfaceNode: AstTypes.TSInterfaceDeclaration | undefined;

// prettier-ignore
Walker.walk(globalDecl as AstTypes.ASTNode, {}, {
TSModuleDeclaration(node, { next }) {
if (node.id.type === 'Identifier' && node.id.name === 'App') {
app = node;
}
next();
},
TSInterfaceDeclaration(node) {
if (node.id.type === 'Identifier' && node.id.name === name) {
interfaceNode = node;
}
},
});

if (!app) {
app = common.statementFromString('namespace App {}') as AstTypes.TSModuleDeclaration;
globalDecl.body.body.push(app);
}

if (app.body?.type !== 'TSModuleBlock') {
throw new Error('Unexpected body type of `namespace App` in `src/app.d.ts`');
}

if (!interfaceNode) {
// add the interface if it's missing
interfaceNode = common.statementFromString(
`interface ${name} {}`
) as AstTypes.TSInterfaceDeclaration;
app.body.body.push(interfaceNode);
}

return interfaceNode;
}

export function hasTypeProp(
name: string,
node: AstTypes.TSInterfaceDeclaration['body']['body'][number]
) {
return (
node.type === 'TSPropertySignature' && node.key.type === 'Identifier' && node.key.name === name
);
}

export function addHooksHandle(
ast: AstTypes.Program,
typescript: boolean,
newHandleName: string,
handleContent: string,
forceSeparateHandle: boolean = false
) {
if (typescript) {
imports.addNamed(ast, '@sveltejs/kit', { Handle: 'Handle' }, true);
}

let isSpecifier: boolean = false;
let handleName = 'handle';
let exportDecl: AstTypes.ExportNamedDeclaration | undefined;
let originalHandleDecl: AstKinds.DeclarationKind | undefined;

// We'll first visit all of the named exports and grab their references if they export `handle`.
// This will grab export references for:
// `export { handle }` & `export { foo as handle }`
// `export const handle = ...`, & `export function handle() {...}`
// prettier-ignore
Walker.walk(ast as AstTypes.ASTNode, {}, {
ExportNamedDeclaration(node) {
let maybeHandleDecl: AstKinds.DeclarationKind | undefined;

// `export { handle }` & `export { foo as handle }`
const handleSpecifier = node.specifiers?.find((s) => s.exported.name === 'handle');
if (handleSpecifier) {
isSpecifier = true;
// we'll search for the local name in case it's aliased (e.g. `export { foo as handle }`)
handleName = handleSpecifier.local?.name ?? handleSpecifier.exported.name;

// find the definition
const handleFunc = ast.body.find((n) => isFunctionDeclaration(n, handleName));
const handleVar = ast.body.find((n) => isVariableDeclaration(n, handleName));

maybeHandleDecl = handleFunc ?? handleVar;
}

maybeHandleDecl ??= node.declaration ?? undefined;

// `export const handle`
if (maybeHandleDecl && isVariableDeclaration(maybeHandleDecl, handleName)) {
exportDecl = node;
originalHandleDecl = maybeHandleDecl;
}

// `export function handle`
if (maybeHandleDecl && isFunctionDeclaration(maybeHandleDecl, handleName)) {
exportDecl = node;
originalHandleDecl = maybeHandleDecl;
}
},
});

const newHandle = common.expressionFromString(handleContent);
if (common.hasNode(ast, newHandle)) return;

// This is the straightforward case. If there's no existing `handle`, we'll just add one
// with the new handle's definition and exit
if (!originalHandleDecl || !exportDecl) {
// handle declaration doesn't exist, so we'll just create it with the hook
const newDecl = variables.declaration(ast, 'const', handleName, newHandle);
if (typescript) {
const declarator = newDecl.declarations[0] as AstTypes.VariableDeclarator;
variables.typeAnnotateDeclarator(declarator, 'Handle');
}

if (!forceSeparateHandle) exports.namedExport(ast, handleName, newDecl);
else {
const newDecl = variables.declaration(ast, 'const', newHandleName, newHandle);
if (typescript) {
const declarator = newDecl.declarations[0] as AstTypes.VariableDeclarator;
variables.typeAnnotateDeclarator(declarator, 'Handle');
}
ast.body.push(newDecl);

const handleDecl = variables.declaration(
ast,
'const',
handleName,
common.expressionFromString(newHandleName)
);
if (typescript) {
const declarator = handleDecl.declarations[0] as AstTypes.VariableDeclarator;
variables.typeAnnotateDeclarator(declarator, 'Handle');
}
exports.namedExport(ast, handleName, handleDecl);
}

return;
}

// create the new handle
const newDecl = variables.declaration(ast, 'const', newHandleName, newHandle);
if (typescript) {
const declarator = newDecl.declarations[0] as AstTypes.VariableDeclarator;
variables.typeAnnotateDeclarator(declarator, 'Handle');
}

// check if `handle` is using a sequence
let sequence: AstTypes.CallExpression | undefined;
if (originalHandleDecl.type === 'VariableDeclaration') {
const handle = originalHandleDecl.declarations.find(
(d) => d.type === 'VariableDeclarator' && usingSequence(d, handleName)
) as AstTypes.VariableDeclarator | undefined;

sequence = handle?.init as AstTypes.CallExpression;
}

// If `handle` is already using a `sequence`, then we'll just create the new handle and
// append the new handle name to the args of `sequence`
// e.g. `export const handle = sequence(some, other, handles, newHandle);`
if (sequence) {
const hasNewArg = sequence.arguments.some(
(arg) => arg.type === 'Identifier' && arg.name === newHandleName
);
if (!hasNewArg) {
sequence.arguments.push(variables.identifier(newHandleName));
}

// removes the declarations so we can append them in the correct order
ast.body = ast.body.filter(
(n) => n !== originalHandleDecl && n !== exportDecl && n !== newDecl
);
if (isSpecifier) {
// if export specifiers are being used (e.g. `export { handle }`), then we'll want
// need to also append original handle declaration as it's not part of the export declaration
ast.body.push(newDecl, originalHandleDecl, exportDecl);
} else {
ast.body.push(newDecl, exportDecl);
}

return;
}

// At this point, the existing `handle` doesn't call `sequence`, so we'll need to rename the original
// `handle` and create a new `handle` that uses `sequence`
// e.g. `const handle = sequence(originalHandle, newHandle);`
const NEW_HANDLE_NAME = 'originalHandle';
const sequenceCall = functions.callByIdentifier('sequence', [NEW_HANDLE_NAME, newHandleName]);
const newHandleDecl = variables.declaration(ast, 'const', handleName, sequenceCall);

imports.addNamed(ast, '@sveltejs/kit/hooks', { sequence: 'sequence' });

let renameRequired = false;
// rename `export const handle`
if (originalHandleDecl && isVariableDeclaration(originalHandleDecl, handleName)) {
const handle = getVariableDeclarator(originalHandleDecl, handleName);
if (handle && handle.id.type === 'Identifier' && handle.init?.type !== 'Identifier') {
renameRequired = true;
handle.id.name = NEW_HANDLE_NAME;
}
}
// rename `export function handle`
if (originalHandleDecl && isFunctionDeclaration(originalHandleDecl, handleName)) {
renameRequired = true;
originalHandleDecl.id!.name = NEW_HANDLE_NAME;
}

// removes all declarations so that we can re-append them in the correct order
ast.body = ast.body.filter((n) => n !== originalHandleDecl && n !== exportDecl && n !== newDecl);

if (isSpecifier) {
ast.body.push(originalHandleDecl, newDecl, newHandleDecl, exportDecl);
}

if (exportDecl.declaration && renameRequired) {
// when we re-append the declarations, we only want to add the declaration
// of the (now renamed) original `handle` _without_ the `export` keyword:
// e.g. `const originalHandle = ...;`
ast.body.push(exportDecl.declaration, newDecl);
// `export const handle = sequence(originalHandle, newHandle);`
exports.namedExport(ast, handleName, newHandleDecl);
} else if (exportDecl.declaration && isVariableDeclaration(originalHandleDecl, handleName)) {
// if the previous value of `export const handle = ...` was an identifier
// there is no need to rename the handle, we just need to add it to the sequence
const variableDeclarator = getVariableDeclarator(originalHandleDecl, handleName);
const sequenceCall = functions.callByIdentifier('sequence', [
(variableDeclarator?.init as AstTypes.Identifier).name,
newHandleName
]);
const newHandleDecl = variables.declaration(ast, 'const', handleName, sequenceCall);
if (typescript) {
const declarator = newHandleDecl.declarations[0] as AstTypes.VariableDeclarator;
variables.typeAnnotateDeclarator(declarator, 'Handle');
}
ast.body.push(newDecl);
exports.namedExport(ast, handleName, newHandleDecl);
}
}

function usingSequence(node: AstTypes.VariableDeclarator, handleName: string) {
return (
node.id.type === 'Identifier' &&
node.id.name === handleName &&
node.init?.type === 'CallExpression' &&
node.init.callee.type === 'Identifier' &&
node.init.callee.name === 'sequence'
);
}

function isVariableDeclaration(
node: AstTypes.ASTNode,
variableName: string
): node is AstTypes.VariableDeclaration {
return (
node.type === 'VariableDeclaration' && getVariableDeclarator(node, variableName) !== undefined
);
}

function getVariableDeclarator(
node: AstTypes.VariableDeclaration,
handleName: string
): AstTypes.VariableDeclarator | undefined {
return node.declarations.find(
(d) => d.type === 'VariableDeclarator' && d.id.type === 'Identifier' && d.id.name === handleName
) as AstTypes.VariableDeclarator | undefined;
}

function isFunctionDeclaration(
node: AstTypes.ASTNode,
funcName: string
): node is AstTypes.FunctionDeclaration {
return node.type === 'FunctionDeclaration' && node.id?.name === funcName;
}
10 changes: 4 additions & 6 deletions packages/adders/drizzle/config/adder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ export const adder = defineAdderConfig({
}
},
options: availableOptions,
integrationType: 'inline',
packages: [
{ name: 'drizzle-orm', version: '^0.33.0', dev: false },
{ name: 'drizzle-kit', version: '^0.22.0', dev: true },
Expand Down Expand Up @@ -328,15 +327,14 @@ export const adder = defineAdderConfig({
}
}
],
nextSteps: ({ options, colors }) => {
const highlight = (str: string) => colors.bold(colors.cyan(str));
nextSteps: ({ options, highlighter }) => {
const steps = [
`You will need to set ${colors.yellow('DATABASE_URL')} in your production environment`
`You will need to set ${highlighter.env('DATABASE_URL')} in your production environment`
];
if (options.docker) {
steps.push(`Run ${highlight('npm run db:start')} to start the docker container`);
steps.push(`Run ${highlighter.command('npm run db:start')} to start the docker container`);
}
steps.push(`To update your DB schema, run ${highlight('npm run db:push')}`);
steps.push(`To update your DB schema, run ${highlighter.command('npm run db:push')}`);

return steps;
}
Expand Down
1 change: 0 additions & 1 deletion packages/adders/eslint/config/adder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ export const adder = defineAdderConfig({
}
},
options,
integrationType: 'inline',
packages: [
{ name: 'eslint', version: '^9.7.0', dev: true },
{ name: '@types/eslint', version: '^9.6.0', dev: true },
Expand Down
Loading
Loading