Skip to content

Commit

Permalink
Added configurations for solid template with helper and generator fun…
Browse files Browse the repository at this point in the history
…ctions
  • Loading branch information
k8pai committed Sep 24, 2023
1 parent 269b5f5 commit 6dc4b83
Show file tree
Hide file tree
Showing 5 changed files with 403 additions and 11 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"description": "A nextauth cli to setup a basic application Setup running",
"exports": "./dist/index.js",
"bin": {
"solidauth": "./dist/solid.js",
"nextauth": "./dist/nextauth.js",
"svelteauth": "./dist/sveltekit.js"
},
Expand Down
58 changes: 57 additions & 1 deletion src/lib/generators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,18 @@ import {
CreateFolderAndWrite,
GenerateAdapterConfigurations,
GenerateEnvVariables,
GenerateSolidTemplate,
GenerateSveltekitEnvVariables,
GenerateSveltekitTemplate,
GenerateTemplate,
sleep,
} from './helpers';
import { ExtentionTypes, OptionsType, SveltekitOptionsType } from '../typings';
import {
ExtentionTypes,
OptionsType,
SolidOptionsType,
SveltekitOptionsType,
} from '../typings';
import { Adapters } from './Adapters';
import { createSpinner } from 'nanospinner';

Expand Down Expand Up @@ -89,3 +95,53 @@ export const SveltekitGenerator = (
// Generate env variables in a .env.example files if env flag is provided.
GenerateAdapterConfigurations(ext, db, adapter);
};

export const SolidGenerator = async (options: SolidOptionsType) => {
const { ts, adapter, env, db, provider, secret, ...config } = options;

let baseDirectory = path.join(process.cwd(), 'src');
let targetDirectory = path.join(baseDirectory, 'routes/api/auth');
let ext: ExtentionTypes = ts ? '.ts' : '.js';
let filePath = path.join(targetDirectory, `[...solidauth]${ext}`);

const solidGenerator = createSpinner('Processing Folder Structure.', {
color: 'cyan',
}).start();

if (!fs.existsSync(baseDirectory)) {
let styledCommand = yellow(bold('npx solidauth'));
let styledIssue = yellow(
italic('https://github.com/k8pai/nextauth-cli/issues'),
);

solidGenerator.error({
text: `Retry with ${styledCommand} or raise an issue - ${styledIssue}`,
});
return;
}
await sleep(400);
solidGenerator.success({
text: 'Folder Structure.',
});

try {
// create initial [...nextauth].{ts/js} files
if (!fs.existsSync(targetDirectory)) {
fs.mkdirSync(targetDirectory, { recursive: true });
}

fs.writeFileSync(
filePath,
GenerateSolidTemplate(config, adapter, env, ts, secret, db),
'utf-8',
);

// Generate env variables in a .env.example files if env flag is provided.
GenerateEnvVariables(options);

// Generate env variables in a .env.example files if env flag is provided.
GenerateAdapterConfigurations(ext, db, adapter, 'src');
} catch (error) {
console.error(red(error as string));
}
};
205 changes: 195 additions & 10 deletions src/lib/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,20 +287,22 @@ export const GenerateEnvVariables = async (options: OptionsType) => {
}
data += `${value.name}=${value.value ?? ''}\n`;
}
data += '\n';
}

if (adapter && Adapters[adapter] && Adapters[adapter].secrets) {
let secrets = Adapters[adapter]?.secrets;
if (secrets.length > 0) {
data += `\n# Environmental variables for ${adapter} Adapter.\n`;
data += `# Environmental variables for ${adapter} Adapter.\n`;
}
for (let secret of secrets) {
data += `${secret}=\n`;
}
data += '\n';
}

if (secret) {
data += `\nNEXTAUTH_SECRET=\n`;
data += `NEXTAUTH_SECRET=\n`;
}

const envGenerator = createSpinner('Generating .env.example file...', {
Expand All @@ -327,56 +329,90 @@ export const GenerateAdapterConfigurations = async (
ext: ExtentionTypes = '.js',
db?: DbTypes,
adapter?: AdapterType,
dir?: 'src',
) => {
if (!adapter || !Adapters[adapter]) {
return;
}

switch (adapter) {
case 'dgraph':
CreateFolderAndWrite('lib', `config${ext}`, GenerateDgraphConfig());
CreateFolderAndWrite(
'lib',
`config${ext}`,
GenerateDgraphConfig(),
dir,
);
break;
case 'drizzle':
CreateFolderAndWrite('lib', 'schema.ts', GenerateDrizzleSchema(db));
CreateFolderAndWrite(
'lib',
'schema.ts',
GenerateDrizzleSchema(db),
dir,
);
break;
case 'dynamodb':
CreateFolderAndWrite(
'lib',
`dynamodb${ext}`,
GenerateDynamodbConfig(ext),
dir,
);
break;
case 'fauna':
CreateFolderAndWrite('lib', `fauna${ext}`, GenerateFaunaConfig());
CreateFolderAndWrite(
'lib',
`fauna${ext}`,
GenerateFaunaConfig(),
dir,
);
break;
case 'firebase':
CreateFolderAndWrite(
'lib',
`firestore${ext}`,
GenerateFirebaseConfig(),
dir,
);
break;
case 'kysely':
CreateFolderAndWrite('lib', `db.ts`, GenerateKyselyConfig());
CreateFolderAndWrite('lib', `db.ts`, GenerateKyselyConfig(), dir);
break;
case 'mikroOrm':
CreateFolderAndWrite('lib', `config.ts`, GenerateMikroOrmConfig());
CreateFolderAndWrite(
'lib',
`config.ts`,
GenerateMikroOrmConfig(),
dir,
);
break;
case 'mongodb':
CreateFolderAndWrite(
'lib',
`mongodb${ext}`,
GenerateMongodbClient(ext),
dir,
);
break;
case 'neo4j':
CreateFolderAndWrite('lib', `config${ext}`, GenerateNeo4jConfig());
CreateFolderAndWrite(
'lib',
`config${ext}`,
GenerateNeo4jConfig(),
dir,
);
break;
case 'pouchdb':
// GenerateKyselyAdapter(ext);
break;
case 'prisma':
CreateFolderAndWrite('lib', `prisma${ext}`, GeneratePrismaConfig());
CreateFolderAndWrite(
'lib',
`prisma${ext}`,
GeneratePrismaConfig(),
dir,
);
CreateFolderAndWrite(
'prisma',
`schema.prisma`,
Expand All @@ -388,20 +424,23 @@ export const GenerateAdapterConfigurations = async (
'lib',
`config${ext}`,
GenerateSequelizeConfig(),
dir,
);
break;
case 'supabase':
CreateFolderAndWrite(
'lib',
`config${ext}`,
GenerateSupabaseConfig(),
dir,
);
break;
case 'upstashRedis':
CreateFolderAndWrite(
'lib',
`redis${ext}`,
GenerateUpstashRedisConfig(),
dir,
);
break;
}
Expand All @@ -411,8 +450,12 @@ export const CreateFolderAndWrite = (
folder: string,
file: string,
content: string,
dir?: 'src',
) => {
const lib = path.join(process.cwd(), folder);
const lib = path.join(
dir ? path.join(process.cwd(), dir) : process.cwd(),
folder,
);
const fileName = path.join(lib, file);

if (!fs.existsSync(lib)) {
Expand Down Expand Up @@ -679,3 +722,145 @@ export const GenerateSveltekitEnvVariables = async (
text: `${styledEnv} Generated.`,
});
};

// solid helper functions.
export const GenerateSolidTemplate = (
rest: ProviderType,
adapter?: AdapterType,
env?: boolean,
ts?: boolean,
secret?: boolean,
db?: DbTypes,
) => {
const { allImports: solidImports } = GenerateSolidImports(
rest,
adapter,
ts,
);

const { providerOptions, adapterOptions, secretOptions } =
GenerateSolidAuthOptions(rest, adapter, ts, secret);

return `${solidImports}
export const authOpts${ts ? ': SolidAuthConfig' : ''} = {
providers: [${providerOptions}
],${adapterOptions}${secretOptions}
debug: false,
}
export const { GET, POST } = SolidAuth(authOpts)`;
};

export const GenerateSolidImports = (
options: ProviderType,
adapter?: AdapterType,
ts?: boolean,
) => {
let adapterImports = '',
providerImports = `import { SolidAuth${
ts ? ', type SolidAuthConfig' : ''
} } from "@auth/solid-start";\n`;

for (let val in options) {
const { importOptions } = providers[val as ProviderOptions];
for (let { defaultImport, authName, authPath } of importOptions) {
providerImports += `import ${
defaultImport ? `${authName}` : `{ ${authName} }`
} from '${authPath}';\n`;
}
}

let temp = ``;
for (let val in options) {
const {
options: { Generator, ...envSecrets },
} = providers[val as ProviderOptions];

for (let [key, value] of Object.entries(envSecrets)) {
if (typeof value === 'string') {
temp += `${value}-`;
continue;
}
temp += `${value.name}-`;
}
}

// logic for adapter imports if any adapters are present...
if (adapter && Adapters[adapter]) {
let { importOptions } = Adapters[adapter];
for (let { defaultImport, name, path } of importOptions) {
adapterImports += `import ${
defaultImport ? `${name}` : `{ ${name} }`
} from '${path}';\n`;
}
}

return {
allImports: `${providerImports}${adapterImports}`,
};
};

export const GenerateSolidAuthOptions = (
options: ProviderType,
adapter?: AdapterType,
ts?: boolean,
secret?: boolean,
) => {
let data = ``,
response: {
providerOptions: string;
adapterOptions: string;
secretOptions: string;
} = {
providerOptions: '',
adapterOptions: '',
secretOptions: '',
};
for (const [key, value] of Object.entries(options)) {
if (!value) {
continue;
}
let params = '';
const {
name,
options: { Generator, ...contents },
} = providers[key as ProviderOptions];

// console.log('Generator => ', contents);
if (Generator && typeof Generator !== 'boolean') {
params += Generator();
} else {
for (const [key, value] of Object.entries(contents)) {
if (key === 'Generator') {
continue;
}
if (typeof value === 'string') {
params += `\n\t\t\t${key}: process.env.${value}${
ts ? ' as string' : ''
},`;
continue;
}
const { name, type } = value;
params += `\n\t\t\t${key}: process.env.${name}${
ts ? ` as ${type}` : ''
},`;
}
}

data += `\n\t\t${name}({${params}\n\t\t}),`;
}
response.providerOptions = data;

// Generating Adapters if any...
if (adapter && Adapters[adapter]) {
const { adapterParams: params, importName } = Adapters[adapter];
response.adapterOptions = `\n\tadapter: ${importName}(${params}),`;
}

// Generating Secret fields if any...
if (secret) {
response.secretOptions = `\n\tsecret: process.env.AUTH_SECRET,`;
}

return response;
};
Loading

0 comments on commit 6dc4b83

Please sign in to comment.