Jeu de Donjon IA
Module 1 : Configuration du monorepo
Section intitulée « Module 1 : Configuration du monorepo »Nous allons commencer par créer un nouveau monorepo. Depuis le répertoire de votre choix, exécutez la commande suivante :
npx create-nx-workspace@~21.0.3 dungeon-adventure --pm=pnpm --preset=@aws/nx-plugin --ci=skip
npx create-nx-workspace@~21.0.3 dungeon-adventure --pm=yarn --preset=@aws/nx-plugin --ci=skip
npx create-nx-workspace@~21.0.3 dungeon-adventure --pm=npm --preset=@aws/nx-plugin --ci=skip
npx create-nx-workspace@~21.0.3 dungeon-adventure --pm=bun --preset=@aws/nx-plugin --ci=skip
Cela configurera un monorepo NX dans le répertoire dungeon-adventure
que vous pourrez ensuite ouvrir dans vscode. Il devrait ressembler à ceci :
Répertoire.nx/
- …
Répertoire.vscode/
- …
Répertoirenode_modules/
- …
Répertoirepackages/ emplacement de vos sous-projets
- …
- .gitignore
- .npmrc
- .prettierignore
- .prettierrc
- nx.json configure les paramètres par défaut du CLI Nx et du monorepo
- package.json toutes les dépendances Node sont définies ici
- pnpm-lock.yaml ou bun.lock, yarn.lock, package-lock.json selon le gestionnaire de paquets
- pnpm-workspace.yaml si vous utilisez pnpm
- README.md
- tsconfig.base.json étendu par tous les sous-projets Node
- tsconfig.json
Maintenant, nous sommes prêts à créer nos différents sous-projets en utilisant le @aws/nx-plugin
.
API du jeu
Section intitulée « API du jeu »Commençons par créer notre API de jeu. Pour cela, créons une API tRPC nommée GameApi
en suivant les étapes ci-dessous :
- Installez le Nx Console VSCode Plugin si ce n'est pas déjà fait
- Ouvrez la console Nx dans VSCode
- Cliquez sur
Generate (UI)
dans la section "Common Nx Commands" - Recherchez
@aws/nx-plugin - ts#trpc-api
- Remplissez les paramètres requis
- name: GameApi
- Cliquez sur
Generate
pnpm nx g @aws/nx-plugin:ts#trpc-api --name=GameApi --no-interactive
yarn nx g @aws/nx-plugin:ts#trpc-api --name=GameApi --no-interactive
npx nx g @aws/nx-plugin:ts#trpc-api --name=GameApi --no-interactive
bunx nx g @aws/nx-plugin:ts#trpc-api --name=GameApi --no-interactive
Vous pouvez également effectuer une simulation pour voir quels fichiers seraient modifiés
pnpm nx g @aws/nx-plugin:ts#trpc-api --name=GameApi --no-interactive --dry-run
yarn nx g @aws/nx-plugin:ts#trpc-api --name=GameApi --no-interactive --dry-run
npx nx g @aws/nx-plugin:ts#trpc-api --name=GameApi --no-interactive --dry-run
bunx nx g @aws/nx-plugin:ts#trpc-api --name=GameApi --no-interactive --dry-run
Vous devriez voir de nouveaux fichiers apparaître dans votre arborescence.
Fichiers modifiés par ts#trpc-api
Voici la liste des fichiers générés par le générateur ts#trpc-api
. Examinons quelques fichiers clés :
Répertoirepackages/
Répertoirecommon/
Répertoireconstructs/
Répertoiresrc/
Répertoireapp/ constructs CDK spécifiques
Répertoireapis/
- game-api.ts construct CDK pour l’API tRPC
- index.ts
- …
- index.ts
Répertoirecore/ constructs CDK génériques
Répertoireapi/
- rest-api.ts construct de base pour une API Gateway
- trpc-utils.ts utilitaires pour les constructs tRPC
- utils.ts utilitaires pour les API
- index.ts
- runtime-config.ts
- index.ts
- project.json
- …
Répertoiretypes/ types partagés
Répertoiresrc/
- index.ts
- runtime-config.ts interface utilisée par CDK et le site
- project.json
- …
Répertoiregame-api/ API tRPC
Répertoiresrc/
Répertoireclient/ client vanilla pour appels machine à machine
- index.ts
- sigv4.ts
Répertoiremiddleware/ instrumentation Powertools
- error.ts
- index.ts
- logger.ts
- metrics.ts
- tracer.ts
Répertoireschema/ définitions des entrées/sorties
- echo.ts
Répertoireprocedures/ implémentations des routes
- echo.ts
- index.ts
- init.ts configure le contexte et middleware
- local-server.ts pour exécuter le serveur tRPC localement
- router.ts point d’entrée du handler Lambda
- project.json
- …
- eslint.config.mjs
- vitest.workspace.ts
Examinons quelques fichiers clés :
import { awsLambdaRequestHandler, CreateAWSLambdaContextOptions,} from '@trpc/server/adapters/aws-lambda';import { echo } from './procedures/echo.js';import { t } from './init.js';import { APIGatewayProxyEvent } from 'aws-lambda';
export const router = t.router;
export const appRouter = router({ echo,});
export const handler = awsLambdaRequestHandler({ router: appRouter, createContext: ( ctx: CreateAWSLambdaContextOptions<APIGatewayProxyEvent>, ) => ctx, responseMeta: () => ({ headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': '*', }, }),});
export type AppRouter = typeof appRouter;
Le router définit le point d’entrée de l’API tRPC et déclare toutes les méthodes. La méthode echo
est implémentée dans ./procedures/echo.ts
.
import { publicProcedure } from '../init.js';import { EchoInputSchema, EchoOutputSchema,} from '../schema/echo.js';
export const echo = publicProcedure .input(EchoInputSchema) .output(EchoOutputSchema) .query((opts) => ({ result: opts.input.message }));
Ce fichier implémente la méthode echo
avec des types stricts pour les entrées et sorties.
import { z } from 'zod/v4';
export const EchoInputSchema = z.object({ message: z.string(),});
export type IEchoInput = z.TypeOf<typeof EchoInputSchema>;
export const EchoOutputSchema = z.object({ result: z.string(),});
export type IEchoOutput = z.TypeOf<typeof EchoOutputSchema>;
Les schémas tRPC sont définis avec Zod et exportés comme types TypeScript.
import { Construct } from 'constructs';import * as url from 'url';import { Code, Runtime, Function, FunctionProps, Tracing,} from 'aws-cdk-lib/aws-lambda';import { AuthorizationType, Cors, LambdaIntegration,} from 'aws-cdk-lib/aws-apigateway';import { Duration, Stack } from 'aws-cdk-lib';import { PolicyDocument, PolicyStatement, Effect, AccountPrincipal, AnyPrincipal,} from 'aws-cdk-lib/aws-iam';import { IntegrationBuilder, RestApiIntegration,} from '../../core/api/utils.js';import { RestApi } from '../../core/api/rest-api.js';import { Procedures, routerToOperations } from '../../core/api/trpc-utils.js';import { AppRouter, appRouter } from ':dungeon-adventure/game-api';
type Operations = Procedures<AppRouter>;
export interface GameApiProps< TIntegrations extends Record<Operations, RestApiIntegration>,> { integrations: TIntegrations;}
export class GameApi< TIntegrations extends Record<Operations, RestApiIntegration>,> extends RestApi<Operations, TIntegrations> { public static defaultIntegrations = (scope: Construct) => { return IntegrationBuilder.rest({ operations: routerToOperations(appRouter), defaultIntegrationOptions: { runtime: Runtime.NODEJS_LATEST, handler: 'index.handler', code: Code.fromAsset( url.fileURLToPath( new URL( '../../../../../../dist/packages/game-api/bundle', import.meta.url, ), ), ), timeout: Duration.seconds(30), tracing: Tracing.ACTIVE, environment: { AWS_CONNECTION_REUSE_ENABLED: '1', }, } satisfies FunctionProps, buildDefaultIntegration: (op, props: FunctionProps) => { const handler = new Function(scope, `GameApi${op}Handler`, props); return { handler, integration: new LambdaIntegration(handler) }; }, }); };
constructor( scope: Construct, id: string, props: GameApiProps<TIntegrations>, ) { super(scope, id, { apiName: 'GameApi', defaultMethodOptions: { authorizationType: AuthorizationType.IAM, }, defaultCorsPreflightOptions: { allowOrigins: Cors.ALL_ORIGINS, allowMethods: Cors.ALL_METHODS, }, policy: new PolicyDocument({ statements: [ new PolicyStatement({ effect: Effect.ALLOW, principals: [new AccountPrincipal(Stack.of(scope).account)], actions: ['execute-api:Invoke'], resources: ['execute-api:/*'], }), new PolicyStatement({ effect: Effect.ALLOW, principals: [new AnyPrincipal()], actions: ['execute-api:Invoke'], resources: ['execute-api:/*/OPTIONS/*'], }), ], }), operations: routerToOperations(appRouter), ...props, }); }}
Ce construct CDK définit notre GameApi. La méthode defaultIntegrations
crée automatiquement une fonction Lambda par procédure tRPC.
API des histoires
Section intitulée « API des histoires »Créons maintenant notre API des histoires. Pour cela, utilisons le générateur FastAPI :
- Installez le Nx Console VSCode Plugin si ce n'est pas déjà fait
- Ouvrez la console Nx dans VSCode
- Cliquez sur
Generate (UI)
dans la section "Common Nx Commands" - Recherchez
@aws/nx-plugin - py#fast-api
- Remplissez les paramètres requis
- name: StoryApi
- moduleName: story_api
- Cliquez sur
Generate
pnpm nx g @aws/nx-plugin:py#fast-api --name=StoryApi --moduleName=story_api --no-interactive
yarn nx g @aws/nx-plugin:py#fast-api --name=StoryApi --moduleName=story_api --no-interactive
npx nx g @aws/nx-plugin:py#fast-api --name=StoryApi --moduleName=story_api --no-interactive
bunx nx g @aws/nx-plugin:py#fast-api --name=StoryApi --moduleName=story_api --no-interactive
Vous pouvez également effectuer une simulation pour voir quels fichiers seraient modifiés
pnpm nx g @aws/nx-plugin:py#fast-api --name=StoryApi --moduleName=story_api --no-interactive --dry-run
yarn nx g @aws/nx-plugin:py#fast-api --name=StoryApi --moduleName=story_api --no-interactive --dry-run
npx nx g @aws/nx-plugin:py#fast-api --name=StoryApi --moduleName=story_api --no-interactive --dry-run
bunx nx g @aws/nx-plugin:py#fast-api --name=StoryApi --moduleName=story_api --no-interactive --dry-run
De nouveaux fichiers devraient apparaître.
Fichiers modifiés par py#fast-api
Voici les fichiers générés par py#fast-api
:
Répertoire.venv/ environnement virtuel
- …
Répertoirepackages/
Répertoirecommon/
Répertoireconstructs/
Répertoiresrc/
Répertoireapp/
Répertoireapis/
- story-api.ts construct CDK pour FastAPI
- project.json ajoute une dépendance sur story_api
Répertoiretypes/
Répertoiresrc/
- runtime-config.ts ajoute StoryApi
Répertoirestory_api/
Répertoirestory_api/ module Python
- init.py configure Powertools et FastAPI
- main.py point d’entrée Lambda
Répertoiretests/
- …
- .python-version
- project.json
- pyproject.toml
- .python-version
- pyproject.toml
- uv.lock
// [Code similaire à game-api.ts adapté pour StoryApi]
Ce construct CDK définit notre StoryApi avec une intégration Lambda par opération.
export type ApiUrl = string;export interface IRuntimeConfig { apis: { GameApi: ApiUrl; StoryApi: ApiUrl; };}
Le générateur a mis à jour IRuntimeConfig
pour inclure StoryApi.
from .init import app, lambda_handler, tracer
handler = lambda_handler
@app.get("/")@tracer.capture_methoddef read_root(): return {"Hello": "World"}
Les méthodes API sont définies ici avec Pydantic pour la validation.
Interface utilisateur du jeu : Site web
Section intitulée « Interface utilisateur du jeu : Site web »Créons maintenant l’interface utilisateur avec Cloudscape :
- Installez le Nx Console VSCode Plugin si ce n'est pas déjà fait
- Ouvrez la console Nx dans VSCode
- Cliquez sur
Generate (UI)
dans la section "Common Nx Commands" - Recherchez
@aws/nx-plugin - ts#react-website
- Remplissez les paramètres requis
- name: GameUI
- Cliquez sur
Generate
pnpm nx g @aws/nx-plugin:ts#react-website --name=GameUI --no-interactive
yarn nx g @aws/nx-plugin:ts#react-website --name=GameUI --no-interactive
npx nx g @aws/nx-plugin:ts#react-website --name=GameUI --no-interactive
bunx nx g @aws/nx-plugin:ts#react-website --name=GameUI --no-interactive
Vous pouvez également effectuer une simulation pour voir quels fichiers seraient modifiés
pnpm nx g @aws/nx-plugin:ts#react-website --name=GameUI --no-interactive --dry-run
yarn nx g @aws/nx-plugin:ts#react-website --name=GameUI --no-interactive --dry-run
npx nx g @aws/nx-plugin:ts#react-website --name=GameUI --no-interactive --dry-run
bunx nx g @aws/nx-plugin:ts#react-website --name=GameUI --no-interactive --dry-run
Fichiers modifiés par ts#react-website
Répertoirepackages/
Répertoiregame-ui/
Répertoirepublic/
- …
Répertoiresrc/
Répertoirecomponents/
RépertoireAppLayout/ mise en page globale
- …
Répertoirehooks/
- …
Répertoireroutes/ routage basé fichiers
Répertoirewelcome/
- index.tsx
- index.html
- project.json
- vite.config.ts
// [Code CDK pour le site statique]
// [Code React avec routage]
// [Composant pour la route /welcome]
Le routage est géré de manière typée par @tanstack/react-router
.
Authentification de l’interface
Section intitulée « Authentification de l’interface »Ajoutons l’authentification Cognito :
- Installez le Nx Console VSCode Plugin si ce n'est pas déjà fait
- Ouvrez la console Nx dans VSCode
- Cliquez sur
Generate (UI)
dans la section "Common Nx Commands" - Recherchez
@aws/nx-plugin - ts#react-website#auth
- Remplissez les paramètres requis
- cognitoDomain: game-ui
- project: @dungeon-adventure/game-ui
- allowSignup: true
- Cliquez sur
Generate
pnpm nx g @aws/nx-plugin:ts#react-website#auth --cognitoDomain=game-ui --project=@dungeon-adventure/game-ui --allowSignup=true --no-interactive
yarn nx g @aws/nx-plugin:ts#react-website#auth --cognitoDomain=game-ui --project=@dungeon-adventure/game-ui --allowSignup=true --no-interactive
npx nx g @aws/nx-plugin:ts#react-website#auth --cognitoDomain=game-ui --project=@dungeon-adventure/game-ui --allowSignup=true --no-interactive
bunx nx g @aws/nx-plugin:ts#react-website#auth --cognitoDomain=game-ui --project=@dungeon-adventure/game-ui --allowSignup=true --no-interactive
Vous pouvez également effectuer une simulation pour voir quels fichiers seraient modifiés
pnpm nx g @aws/nx-plugin:ts#react-website#auth --cognitoDomain=game-ui --project=@dungeon-adventure/game-ui --allowSignup=true --no-interactive --dry-run
yarn nx g @aws/nx-plugin:ts#react-website#auth --cognitoDomain=game-ui --project=@dungeon-adventure/game-ui --allowSignup=true --no-interactive --dry-run
npx nx g @aws/nx-plugin:ts#react-website#auth --cognitoDomain=game-ui --project=@dungeon-adventure/game-ui --allowSignup=true --no-interactive --dry-run
bunx nx g @aws/nx-plugin:ts#react-website#auth --cognitoDomain=game-ui --project=@dungeon-adventure/game-ui --allowSignup=true --no-interactive --dry-run
Fichiers modifiés par ts#react-website#auth
Répertoirepackages/
Répertoiregame-ui/
Répertoiresrc/
Répertoirecomponents/
RépertoireCognitoAuth/
- …
RépertoireRuntimeConfig/
- …
Répertoirehooks/
- useRuntimeConfig.tsx
// [Ajout des providers Cognito et RuntimeConfig]
Connexion de l’UI à Story API
Section intitulée « Connexion de l’UI à Story API »Connectons l’UI à StoryApi :
- Installez le Nx Console VSCode Plugin si ce n'est pas déjà fait
- Ouvrez la console Nx dans VSCode
- Cliquez sur
Generate (UI)
dans la section "Common Nx Commands" - Recherchez
@aws/nx-plugin - api-connection
- Remplissez les paramètres requis
- sourceProject: @dungeon-adventure/game-ui
- targetProject: dungeon_adventure.story_api
- Cliquez sur
Generate
pnpm nx g @aws/nx-plugin:api-connection --sourceProject=@dungeon-adventure/game-ui --targetProject=dungeon_adventure.story_api --no-interactive
yarn nx g @aws/nx-plugin:api-connection --sourceProject=@dungeon-adventure/game-ui --targetProject=dungeon_adventure.story_api --no-interactive
npx nx g @aws/nx-plugin:api-connection --sourceProject=@dungeon-adventure/game-ui --targetProject=dungeon_adventure.story_api --no-interactive
bunx nx g @aws/nx-plugin:api-connection --sourceProject=@dungeon-adventure/game-ui --targetProject=dungeon_adventure.story_api --no-interactive
Vous pouvez également effectuer une simulation pour voir quels fichiers seraient modifiés
pnpm nx g @aws/nx-plugin:api-connection --sourceProject=@dungeon-adventure/game-ui --targetProject=dungeon_adventure.story_api --no-interactive --dry-run
yarn nx g @aws/nx-plugin:api-connection --sourceProject=@dungeon-adventure/game-ui --targetProject=dungeon_adventure.story_api --no-interactive --dry-run
npx nx g @aws/nx-plugin:api-connection --sourceProject=@dungeon-adventure/game-ui --targetProject=dungeon_adventure.story_api --no-interactive --dry-run
bunx nx g @aws/nx-plugin:api-connection --sourceProject=@dungeon-adventure/game-ui --targetProject=dungeon_adventure.story_api --no-interactive --dry-run
Fichiers modifiés par api-connection
Répertoirepackages/
Répertoiregame-ui/
Répertoiresrc/
Répertoirehooks/
- useSigV4.tsx
- useStoryApiClient.tsx
Répertoirecomponents/
- QueryClientProvider.tsx
- StoryApiProvider.tsx
// [Client généré pour StoryApi]
// [Provider pour les hooks TanStack Query]
Connexion de l’UI à Game API
Section intitulée « Connexion de l’UI à Game API »Connectons l’UI à GameApi :
- Installez le Nx Console VSCode Plugin si ce n'est pas déjà fait
- Ouvrez la console Nx dans VSCode
- Cliquez sur
Generate (UI)
dans la section "Common Nx Commands" - Recherchez
@aws/nx-plugin - api-connection
- Remplissez les paramètres requis
- sourceProject: @dungeon-adventure/game-ui
- targetProject: @dungeon-adventure/game-api
- Cliquez sur
Generate
pnpm nx g @aws/nx-plugin:api-connection --sourceProject=@dungeon-adventure/game-ui --targetProject=@dungeon-adventure/game-api --no-interactive
yarn nx g @aws/nx-plugin:api-connection --sourceProject=@dungeon-adventure/game-ui --targetProject=@dungeon-adventure/game-api --no-interactive
npx nx g @aws/nx-plugin:api-connection --sourceProject=@dungeon-adventure/game-ui --targetProject=@dungeon-adventure/game-api --no-interactive
bunx nx g @aws/nx-plugin:api-connection --sourceProject=@dungeon-adventure/game-ui --targetProject=@dungeon-adventure/game-api --no-interactive
Vous pouvez également effectuer une simulation pour voir quels fichiers seraient modifiés
pnpm nx g @aws/nx-plugin:api-connection --sourceProject=@dungeon-adventure/game-ui --targetProject=@dungeon-adventure/game-api --no-interactive --dry-run
yarn nx g @aws/nx-plugin:api-connection --sourceProject=@dungeon-adventure/game-ui --targetProject=@dungeon-adventure/game-api --no-interactive --dry-run
npx nx g @aws/nx-plugin:api-connection --sourceProject=@dungeon-adventure/game-ui --targetProject=@dungeon-adventure/game-api --no-interactive --dry-run
bunx nx g @aws/nx-plugin:api-connection --sourceProject=@dungeon-adventure/game-ui --targetProject=@dungeon-adventure/game-api --no-interactive --dry-run
Fichiers modifiés par api-connection
Répertoirepackages/
Répertoiregame-ui/
Répertoiresrc/
Répertoirecomponents/
- GameApiClientProvider.tsx
Répertoirehooks/
- useGameApi.tsx
// [Hook tRPC pour GameApi]
// [Ajout des providers tRPC]
Infrastructure du jeu
Section intitulée « Infrastructure du jeu »Créons le projet d’infrastructure CDK :
- Installez le Nx Console VSCode Plugin si ce n'est pas déjà fait
- Ouvrez la console Nx dans VSCode
- Cliquez sur
Generate (UI)
dans la section "Common Nx Commands" - Recherchez
@aws/nx-plugin - ts#infra
- Remplissez les paramètres requis
- name: infra
- Cliquez sur
Generate
pnpm nx g @aws/nx-plugin:ts#infra --name=infra --no-interactive
yarn nx g @aws/nx-plugin:ts#infra --name=infra --no-interactive
npx nx g @aws/nx-plugin:ts#infra --name=infra --no-interactive
bunx nx g @aws/nx-plugin:ts#infra --name=infra --no-interactive
Vous pouvez également effectuer une simulation pour voir quels fichiers seraient modifiés
pnpm nx g @aws/nx-plugin:ts#infra --name=infra --no-interactive --dry-run
yarn nx g @aws/nx-plugin:ts#infra --name=infra --no-interactive --dry-run
npx nx g @aws/nx-plugin:ts#infra --name=infra --no-interactive --dry-run
bunx nx g @aws/nx-plugin:ts#infra --name=infra --no-interactive --dry-run
Fichiers modifiés par ts#infra
Répertoirepackages/
Répertoireinfra/
Répertoiresrc/
Répertoirestacks/
- application-stack.ts
- main.ts
// [Application CDK avec validation cfn-guard]
// [Définition des ressources CDK]
Mise à jour de l’infrastructure
Section intitulée « Mise à jour de l’infrastructure »Mettons à jour application-stack.ts
pour instancier nos constructs :
import { GameApi, GameUI, StoryApi, UserIdentity,} from ':dungeon-adventure/common-constructs';import * as cdk from 'aws-cdk-lib';import { Construct } from 'constructs';
export class ApplicationStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props);
// The code that defines your stack goes here const userIdentity = new UserIdentity(this, 'UserIdentity');
const gameApi = new GameApi(this, 'GameApi', { integrations: GameApi.defaultIntegrations(this).build(), }); const storyApi = new StoryApi(this, 'StoryApi', { integrations: StoryApi.defaultIntegrations(this).build(), });
// grant our authenticated role access to invoke our APIs [storyApi, gameApi].forEach((api) => api.grantInvokeAccess(userIdentity.identityPool.authenticatedRole), );
// Ensure this is instantiated last so our runtime-config.json can be automatically configured new GameUI(this, 'GameUI'); }}
Construction du code
Section intitulée « Construction du code »Commandes Nx
Visualisation des dépendances
Section intitulée « Visualisation des dépendances »pnpm nx graph
yarn nx graph
npx nx graph
bunx nx graph

Ajoutez --skip-nx-cache
pour ignorer le cache :
pnpm nx run @dungeon-adventure/infra:build --skip-nx-cache
yarn nx run @dungeon-adventure/infra:build --skip-nx-cache
npx nx run @dungeon-adventure/infra:build --skip-nx-cache
bunx nx run @dungeon-adventure/infra:build --skip-nx-cache
pnpm nx run-many --target build --all
yarn nx run-many --target build --all
npx nx run-many --target build --all
bunx nx run-many --target build --all
? Souhaitez-vous synchroniser les changements pour mettre à jour l'espace de travail ? …Oui, synchroniser et exécuter les tâches
Sélectionnez Oui pour résoudre les références TypeScript.
Les artefacts construits sont dans dist/
. Félicitations ! 🎉🎉🎉