diff --git a/modularium/cli/add/utils.ts b/modularium/cli/add/utils.ts index ae0654f..c9c0e3a 100644 --- a/modularium/cli/add/utils.ts +++ b/modularium/cli/add/utils.ts @@ -59,18 +59,28 @@ const runCommands = async (source: string, destination: string) => { schema: `${destination}/schema.graphql`, }, ]); + const modulesFolderPaths = destination.split('/'); + const modulesFolder = modulesFolderPaths.slice(0, -1).join('/'); fs.mkdirSync(destination, { recursive: true }); const clone = runCommand(`git clone -n --depth=1 --filter=tree:0 ${BASE_REPOSITORY} ${TEMP_REPO_NAME}`); if (!clone) return { error: "can't clone repository" }; - const checkout = runCommand( - `cd ${TEMP_REPO_NAME} && git config core.sparseCheckout true && git sparse-checkout set ${source} && git checkout && git config core.sparseCheckout false`, - ); - if (!checkout) return { error: "can't checkout repository" }; let move; if (system.platform === 'win32') { - move = runCommand(`move ${TEMP_REPO_NAME}/${source} ${destination} && del ${TEMP_REPO_NAME}`); - } else move = runCommand(`mv ${TEMP_REPO_NAME}/${source} ${destination} && rm -rf ${TEMP_REPO_NAME}`); + move = runCommand( + `cd ${TEMP_REPO_NAME} && git config core.sparseCheckout true && git sparse-checkout set ${source} && git checkout && git config core.sparseCheckout false && cd .. && move ${TEMP_REPO_NAME}/${source} ${modulesFolder} && del ${TEMP_REPO_NAME}`, + ); + } else + move = runCommand( + `cd ${TEMP_REPO_NAME} && \ + git config core.sparseCheckout true && \ + git sparse-checkout set ${source} && \ + git checkout && \ + git config core.sparseCheckout false && \ + cd .. && \ + mv ${TEMP_REPO_NAME}/${source} ${modulesFolder} && \ + rm -rf ${TEMP_REPO_NAME}`, + ); if (!move) return { error: "can't move repository" }; // deps should be installed from docs. Later one we can install deps here somehow return { success: true }; diff --git a/modularium/playground/.eslintrc.json b/modularium/playground/.eslintrc.json new file mode 100644 index 0000000..b9ec89d --- /dev/null +++ b/modularium/playground/.eslintrc.json @@ -0,0 +1,7 @@ +{ + "extends":["../../.eslintrc.json"], + "rules": { + "@typescript-eslint/no-explicit-any":0 + } +} + \ No newline at end of file diff --git a/modularium/playground/.gitignore b/modularium/playground/.gitignore new file mode 100644 index 0000000..964a3d0 --- /dev/null +++ b/modularium/playground/.gitignore @@ -0,0 +1,4 @@ +.env +/lib +/node_modules +.graphql-editor-auth.json \ No newline at end of file diff --git a/modularium/playground/.prettierrc b/modularium/playground/.prettierrc new file mode 100644 index 0000000..d515f04 --- /dev/null +++ b/modularium/playground/.prettierrc @@ -0,0 +1,8 @@ +{ + "arrowParens": "always", + "semi": true, + "trailingComma": "all", + "singleQuote": true, + "printWidth": 120, + "tabWidth": 2 +} diff --git a/modularium/playground/axolotl.json b/modularium/playground/axolotl.json new file mode 100644 index 0000000..b5589f2 --- /dev/null +++ b/modularium/playground/axolotl.json @@ -0,0 +1,4 @@ +{ + "schema": "schema.graphql", + "models": "src/models.ts" +} \ No newline at end of file diff --git a/modularium/playground/package.json b/modularium/playground/package.json new file mode 100644 index 0000000..adac8e9 --- /dev/null +++ b/modularium/playground/package.json @@ -0,0 +1,19 @@ +{ + "name": "@aexol/modularium-playground", + "version": "0.4.1", + "description": "Axolotl modularium", + "main": "lib/index.js", + "type": "module", + "private": true, + "publishConfig": { + "access": "restricted" + }, + "scripts": { + "start": "modularium add users" + }, + "author": "GraphQL Editor Centaur Generator", + "license": "ISC", + "devDependencies": { + "@aexol/modularium": "^0.4.1" + } +} diff --git a/modularium/playground/src/axolotl.ts b/modularium/playground/src/axolotl.ts new file mode 100644 index 0000000..66d60db --- /dev/null +++ b/modularium/playground/src/axolotl.ts @@ -0,0 +1,8 @@ +import { Models } from '@/src/models.js'; +import { Axolotl } from '@aexol/axolotl-core'; +import { graphqlYogaAdapter } from '@aexol/axolotl-graphql-yoga'; + +export const { applyMiddleware, createResolvers, createDirectives, adapter } = Axolotl(graphqlYogaAdapter)< + Models, + unknown +>(); diff --git a/modularium/playground/src/index.ts b/modularium/playground/src/index.ts new file mode 100644 index 0000000..54f0344 --- /dev/null +++ b/modularium/playground/src/index.ts @@ -0,0 +1,8 @@ +import { adapter } from '@/src/axolotl.js'; +import resolvers from '@/src/resolvers.js'; + +// This is yoga specific + +adapter({ resolvers }).server.listen(parseInt(process.env.PORT || '4000'), () => { + console.log('LISTENING to ' + process.env.PORT || '4000'); +}); diff --git a/modularium/playground/src/models.ts b/modularium/playground/src/models.ts new file mode 100644 index 0000000..642c7ee --- /dev/null +++ b/modularium/playground/src/models.ts @@ -0,0 +1,449 @@ +export enum EditUserError { + USERNAME_ALREADY_TAKEN = 'USERNAME_ALREADY_TAKEN', + FAILED_MONGO_UPDATE = 'FAILED_MONGO_UPDATE', + USER_DOES_NOT_EXIST = 'USER_DOES_NOT_EXIST', +} +export enum VerifyEmailError { + TOKEN_CANNOT_BE_FOUND = 'TOKEN_CANNOT_BE_FOUND', +} +export enum ChangePasswordWhenLoggedError { + CANNOT_CHANGE_PASSWORD_FOR_USER_REGISTERED_VIA_SOCIAL = 'CANNOT_CHANGE_PASSWORD_FOR_USER_REGISTERED_VIA_SOCIAL', + OLD_PASSWORD_IS_INVALID = 'OLD_PASSWORD_IS_INVALID', + PASSWORD_WEAK = 'PASSWORD_WEAK', +} +export enum ChangePasswordWithTokenError { + CANNOT_CHANGE_PASSWORD_FOR_USER_REGISTERED_VIA_SOCIAL = 'CANNOT_CHANGE_PASSWORD_FOR_USER_REGISTERED_VIA_SOCIAL', + TOKEN_IS_INVALID = 'TOKEN_IS_INVALID', + PASSWORD_IS_TOO_WEAK = 'PASSWORD_IS_TOO_WEAK', +} +export enum SquashAccountsError { + YOU_HAVE_ONLY_ONE_ACCOUNT = 'YOU_HAVE_ONLY_ONE_ACCOUNT', + YOUR_ACCOUNTS_DO_NOT_HAVE_CONFIRMED_EMAIL = 'YOUR_ACCOUNTS_DO_NOT_HAVE_CONFIRMED_EMAIL', + INCORRECT_PASSWORD = 'INCORRECT_PASSWORD', +} +export enum IntegrateSocialAccountError { + YOU_HAVE_ONLY_ONE_ACCOUNT = 'YOU_HAVE_ONLY_ONE_ACCOUNT', + YOUR_ACCOUNT_DOES_NOT_HANDLE_CHANGE_PASSWORD_MODE = 'YOUR_ACCOUNT_DOES_NOT_HANDLE_CHANGE_PASSWORD_MODE', + INCORRECT_PASSWORD = 'INCORRECT_PASSWORD', + CANNOT_FIND_USER = 'CANNOT_FIND_USER', + YOUR_ACCOUNT_DOES_NOT_HAVE_CONFIRMED_EMAIL = 'YOUR_ACCOUNT_DOES_NOT_HAVE_CONFIRMED_EMAIL', +} +export enum GenerateOAuthTokenError { + TOKEN_NOT_GENERATED = 'TOKEN_NOT_GENERATED', + CANNOT_RETRIEVE_USER_INFORMATION_FROM_APPLE = 'CANNOT_RETRIEVE_USER_INFORMATION_FROM_APPLE', +} +export enum SocialKind { + Google = 'Google', + Github = 'Github', + Apple = 'Apple', + Microsoft = 'Microsoft', +} +export enum RegisterErrors { + USERNAME_EXISTS = 'USERNAME_EXISTS', + PASSWORD_WEAK = 'PASSWORD_WEAK', + INVITE_DOMAIN_INCORRECT = 'INVITE_DOMAIN_INCORRECT', + LINK_EXPIRED = 'LINK_EXPIRED', + USERNAME_INVALID = 'USERNAME_INVALID', +} +export enum LoginErrors { + CONFIRM_EMAIL_BEFOR_LOGIN = 'CONFIRM_EMAIL_BEFOR_LOGIN', + INVALID_LOGIN_OR_PASSWORD = 'INVALID_LOGIN_OR_PASSWORD', + CANNOT_FIND_CONNECTED_USER = 'CANNOT_FIND_CONNECTED_USER', + YOU_PROVIDED_OTHER_METHOD_OF_LOGIN_ON_THIS_EMAIL = 'YOU_PROVIDED_OTHER_METHOD_OF_LOGIN_ON_THIS_EMAIL', + UNEXPECTED_ERROR = 'UNEXPECTED_ERROR', +} +export enum ProviderErrors { + CANNOT_RETRIVE_PROFILE_FROM_GOOGLE_TRY_REFRESH_TOKEN = 'CANNOT_RETRIVE_PROFILE_FROM_GOOGLE_TRY_REFRESH_TOKEN', + CANNOT_FIND_EMAIL_FOR_THIS_PROFIL = 'CANNOT_FIND_EMAIL_FOR_THIS_PROFIL', + CANNOT_RETRIVE_USER_INFORMATION_FROM_APPLE = 'CANNOT_RETRIVE_USER_INFORMATION_FROM_APPLE', + CODE_IS_NOT_EXIST_IN_ARGS = 'CODE_IS_NOT_EXIST_IN_ARGS', + CANNOT_RETRIVE_SUB_FIELD_FROM_JWT_TOKEN = 'CANNOT_RETRIVE_SUB_FIELD_FROM_JWT_TOKEN', + CANNOT_RETRIVE_TOKEN_FROM_MICROSOFT = 'CANNOT_RETRIVE_TOKEN_FROM_MICROSOFT', +} + +export interface GetOAuthInput { + scopes?: Array | undefined; + state?: string | undefined; + redirectUri?: string | undefined; +} +export interface UpdateUserInput { + username?: string | undefined; + fullName?: string | undefined; + avatarUrl?: string | undefined; +} +export interface GenerateOAuthTokenInput { + social: SocialKind; + code: string; +} +export interface SimpleUserInput { + username: string; + password: string; +} +export interface LoginInput { + username: string; + password: string; +} +export interface VerifyEmailInput { + token: string; +} +export interface ChangePasswordWithTokenInput { + username: string; + forgotToken: string; + newPassword: string; +} +export interface ChangePasswordWhenLoggedInput { + oldPassword: string; + newPassword: string; +} +export interface RegisterInput { + username: string; + password: string; + fullName?: string | undefined; + invitationToken?: string | undefined; +} +export interface ProviderLoginInput { + code: string; + redirectUri: string; +} + +export type Models = { + ['UsersQuery']: { + publicUsers: { + args: Record; + }; + user: { + args: Record; + }; + }; + ['UsersMutation']: { + publicUsers: { + args: Record; + }; + user: { + args: Record; + }; + }; + ['Query']: { + users: { + args: Record; + }; + }; + ['Mutation']: { + users: { + args: Record; + }; + }; + ['AuthorizedUserQuery']: { + me: { + args: Record; + }; + }; + ['AuthorizedUserMutation']: { + changePasswordWhenLogged: { + args: { + changePasswordData: ChangePasswordWhenLoggedInput; + }; + }; + editUser: { + args: { + updatedUser: UpdateUserInput; + }; + }; + integrateSocialAccount: { + args: { + userData: SimpleUserInput; + }; + }; + }; + ['PublicUsersQuery']: { + login: { + args: Record; + }; + getGoogleOAuthLink: { + args: { + setup: GetOAuthInput; + }; + }; + getMicrosoftOAuthLink: { + args: { + setup: GetOAuthInput; + }; + }; + getGithubOAuthLink: { + args: { + setup: GetOAuthInput; + }; + }; + getAppleOAuthLink: { + args: { + setup: GetOAuthInput; + }; + }; + requestForForgotPassword: { + args: { + username: string; + }; + }; + }; + ['PublicUsersMutation']: { + register: { + args: { + user: RegisterInput; + }; + }; + verifyEmail: { + args: { + verifyData: VerifyEmailInput; + }; + }; + changePasswordWithToken: { + args: { + token: ChangePasswordWithTokenInput; + }; + }; + generateOAuthToken: { + args: { + tokenData: GenerateOAuthTokenInput; + }; + }; + }; + ['EditUserResponse']: { + result: { + args: Record; + }; + hasError: { + args: Record; + }; + }; + ['VerifyEmailResponse']: { + result: { + args: Record; + }; + hasError: { + args: Record; + }; + }; + ['ChangePasswordWhenLoggedResponse']: { + result: { + args: Record; + }; + hasError: { + args: Record; + }; + }; + ['ChangePasswordWithTokenResponse']: { + result: { + args: Record; + }; + hasError: { + args: Record; + }; + }; + ['IntegrateSocialAccountResponse']: { + result: { + args: Record; + }; + hasError: { + args: Record; + }; + }; + ['GenerateOAuthTokenResponse']: { + result: { + args: Record; + }; + hasError: { + args: Record; + }; + }; + ['User']: { + username: { + args: Record; + }; + emailConfirmed: { + args: Record; + }; + createdAt: { + args: Record; + }; + fullName: { + args: Record; + }; + avatarUrl: { + args: Record; + }; + _id: { + args: Record; + }; + }; + ['LoginQuery']: { + password: { + args: { + user: LoginInput; + }; + }; + provider: { + args: { + params: ProviderLoginInput; + }; + }; + refreshToken: { + args: { + refreshToken: string; + }; + }; + }; + ['ProviderLoginQuery']: { + apple: { + args: Record; + }; + google: { + args: Record; + }; + github: { + args: Record; + }; + microsoft: { + args: Record; + }; + }; + ['RegisterResponse']: { + registered: { + args: Record; + }; + hasError: { + args: Record; + }; + }; + ['LoginResponse']: { + login: { + args: Record; + }; + accessToken: { + args: Record; + }; + refreshToken: { + args: Record; + }; + hasError: { + args: Record; + }; + }; + ['ProviderResponse']: { + jwt: { + args: Record; + }; + accessToken: { + args: Record; + }; + refreshToken: { + args: Record; + }; + providerAccessToken: { + args: Record; + }; + register: { + args: Record; + }; + hasError: { + args: Record; + }; + }; +}; + +export interface UsersQuery { + publicUsers?: PublicUsersQuery | undefined; + user?: AuthorizedUserQuery | undefined; +} +export interface UsersMutation { + publicUsers?: PublicUsersMutation | undefined; + user?: AuthorizedUserMutation | undefined; +} +export interface Query { + users?: UsersQuery | undefined; +} +export interface Mutation { + users?: UsersMutation | undefined; +} +export interface AuthorizedUserQuery { + me?: User | undefined; +} +export interface AuthorizedUserMutation { + changePasswordWhenLogged: ChangePasswordWhenLoggedResponse; + editUser: EditUserResponse; + integrateSocialAccount: IntegrateSocialAccountResponse; +} +export interface PublicUsersQuery { + login: LoginQuery; + getGoogleOAuthLink: string; + getMicrosoftOAuthLink: string; + getGithubOAuthLink: string; + getAppleOAuthLink: string; + requestForForgotPassword: boolean; +} +export interface PublicUsersMutation { + register: RegisterResponse; + verifyEmail: VerifyEmailResponse; + changePasswordWithToken: ChangePasswordWithTokenResponse; + generateOAuthToken: GenerateOAuthTokenResponse; +} +export interface EditUserResponse { + result?: boolean | undefined; + hasError?: EditUserError | undefined; +} +export interface VerifyEmailResponse { + result?: boolean | undefined; + hasError?: VerifyEmailError | undefined; +} +export interface ChangePasswordWhenLoggedResponse { + result?: boolean | undefined; + hasError?: ChangePasswordWhenLoggedError | undefined; +} +export interface ChangePasswordWithTokenResponse { + result?: boolean | undefined; + hasError?: ChangePasswordWithTokenError | undefined; +} +export interface IntegrateSocialAccountResponse { + result?: boolean | undefined; + hasError?: IntegrateSocialAccountError | undefined; +} +export interface GenerateOAuthTokenResponse { + result?: string | undefined; + hasError?: GenerateOAuthTokenError | undefined; +} +export interface User { + username: string; + emailConfirmed: boolean; + createdAt?: string | undefined; + fullName?: string | undefined; + avatarUrl?: string | undefined; + _id: string; +} +export interface LoginQuery { + password: LoginResponse; + provider: ProviderLoginQuery; + refreshToken: string; +} +export interface ProviderLoginQuery { + apple?: ProviderResponse | undefined; + google?: ProviderResponse | undefined; + github?: ProviderResponse | undefined; + microsoft?: ProviderResponse | undefined; +} +export interface RegisterResponse { + registered?: boolean | undefined; + hasError?: RegisterErrors | undefined; +} +export interface LoginResponse { + login?: string | undefined; + accessToken?: string | undefined; + refreshToken?: string | undefined; + hasError?: LoginErrors | undefined; +} +export interface ProviderResponse { + jwt?: string | undefined; + accessToken?: string | undefined; + refreshToken?: string | undefined; + providerAccessToken?: string | undefined; + register?: boolean | undefined; + hasError?: ProviderErrors | undefined; +} diff --git a/modularium/playground/src/resolvers.ts b/modularium/playground/src/resolvers.ts new file mode 100644 index 0000000..d4f81eb --- /dev/null +++ b/modularium/playground/src/resolvers.ts @@ -0,0 +1,15 @@ +import { mergeAxolotls } from '@aexol/axolotl-core'; +import userResolvers from '@/src/modules/users/resolvers.js'; + +const usersModule = userResolvers({ + sendMailRegister: async (args) => + console.log( + `We don't send mails from modularium:\n\tusername:${args.username}\n\ttoken:${args.authorizationToken}`, + ), + sendMailForgotPassword: async (args) => + console.log( + `We don't send mails from modularium:\n\tusername:${args.username}\n\ttoken:${args.resetPasswordToken}`, + ), +}); + +export default mergeAxolotls(usersModule); diff --git a/modularium/playground/tsconfig.json b/modularium/playground/tsconfig.json new file mode 100644 index 0000000..0a2ed53 --- /dev/null +++ b/modularium/playground/tsconfig.json @@ -0,0 +1,45 @@ +{ + "compilerOptions": { + "sourceMap": true, + "target": "es2022", + "module": "es2022", + "moduleResolution": "node", + "experimentalDecorators": true, + "declaration": true, + "incremental": true, + "removeComments": true, + "noUnusedLocals": true, + "strictNullChecks": true, + "esModuleInterop": true, + "skipLibCheck": true, + "strict": true, + "outDir": "./lib", + "lib": [ + "ESNext", + "DOM", + "DOM.Iterable" + ], + "rootDir": "./src", + "baseUrl": "./", + "composite": true, + "paths": { + "@/*": [ + "./*" + ] + }, + "plugins": [ + { + "transform": "typescript-transform-paths" + }, + { + "transform": "typescript-transform-paths", + "afterDeclarations": true + } + ] + }, + "exclude": [ + "lib", + "node_modules", + "jest.config.js" + ] +} \ No newline at end of file diff --git a/modularium/root/package.json b/modularium/root/package.json index 29656c5..f031e8a 100644 --- a/modularium/root/package.json +++ b/modularium/root/package.json @@ -1,5 +1,5 @@ { - "name": "@aexol/modularium-playground", + "name": "@aexol/modularium-root", "version": "0.4.1", "description": "Axolotl modularium", "main": "lib/index.js", diff --git a/package-lock.json b/package-lock.json index 8721b94..1ddb5da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "packages/cli", "modularium/root", "modularium/cli", + "modularium/playground", "examples/beerpub-yoga", "examples/beerpub-yoga-federated", "examples/beerpub-apollo-server" diff --git a/package.json b/package.json index 039dcb8..e99527e 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "packages/cli", "modularium/root", "modularium/cli", + "modularium/playground", "examples/beerpub-yoga", "examples/beerpub-yoga-federated", "examples/beerpub-apollo-server"