asarazan / martok

https://www.npmjs.com/package/martok
10 stars 0 forks source link

breaks on Node 20 #83

Open janecakemaster opened 1 month ago

janecakemaster commented 1 month ago

our martok script stopped working when converting our project from node 16 to node 20

Generating types for sketchy...
/Users/jane/faceoff-backend/node_modules/martok/dist/typescript/MemberHelpers.js:71
        throw new Error(`Cannot find ${typeWithIssue} in ${source.fileName}`);
              ^
Error: Command failed: martok ./src/games/sketchy/types -o ../faceoff-mobile/shared/src/commonMain/kotlin/com/volley/faceoff/types/games/sketchy --package com.volley.faceoff.types.games.sketchy
martok <path>

Convert a file to kotlin

Options:
      --version             Show version number                        [boolean]
  -o, --out                 output file                                 [string]
  -p, --package             the kotlin package name[string] [default: "example"]
  -t, --dedupeTaggedUnions  Experimental feature that will try to remove any
                            component types of a tagged union and replace
                            references with the optimized class.
                                                      [boolean] [default: false]
  -s, --snakeToCamelCase    convert json-friendly snake_case to Kotlin-friendly
                            camelCase                 [boolean] [default: false]
  -a, --annotationNewLines  Aesthetic option to always put a newline between
                            annotations and declarations
                                                      [boolean] [default: false]
  -i, --importStar          Just throw in an import kotlinx.serialization.*
                                                      [boolean] [default: false]
      --help                Show help                                  [boolean]

Error: Cannot find object in /Users/jane/faceoff-backend/src/games/sketchy/types/Events.ts
    at getMemberType (/Users/jane/faceoff-backend/node_modules/martok/dist/typescript/MemberHelpers.js:71:15)
    at KlassGenerator.generateMemberOrCtorArg (/Users/jane/faceoff-backend/node_modules/martok/dist/martok/declarations/KlassGenerator.js:113:62)
    at /Users/jane/faceoff-backend/node_modules/martok/dist/martok/declarations/KlassGenerator.js:79:29
    at Array.map (<anonymous>)
    at KlassGenerator._generate (/Users/jane/faceoff-backend/node_modules/martok/dist/martok/declarations/KlassGenerator.js:78:34)
    at KlassGenerator.generate (/Users/jane/faceoff-backend/node_modules/martok/dist/martok/declarations/KlassGenerator.js:26:29)
    at /Users/jane/faceoff-backend/node_modules/martok/dist/martok/declarations/TaggedUnionGenerator.js:158:63
    at /Users/jane/faceoff-backend/node_modules/lodash/lodash.js:3585:27
    at /Users/jane/faceoff-backend/node_modules/lodash/lodash.js:4967:15
    at baseForOwn (/Users/jane/faceoff-backend/node_modules/lodash/lodash.js:3032:24)

here seems like its not able to resolve (typeof SketchyGame)['routes']

// src/games/sketchy/types/Events.ts
/**
 * @ignore
 */
import { SketchyGame } from '..';

/**
 * @expand
 */
export type SketchyEvents = EventsRecordToMartok<
  (typeof SketchyGame)['routes']
>;
asarazan commented 1 month ago

Hi Jane nice to meet you! I'm traveling rn but I will def try to look into this shortly. Thanks for filing and say hi to the team for me!

asarazan commented 1 month ago

@janecakemaster could I get you to paste the definition of EventsRecordToMartok as well as any notable or unusual fields that might be in SketchyGame? Even better if you can get a reduced repro that can be dropped into this thread in its entirety.

Once I know what's in EventsRecordToMartok I should be able to dig in and see what's going on.

janecakemaster commented 1 month ago
/**
 * @ignore
 * Convert backend update types to Martok compatible types
 */
export type EventsRecordToMartok<
  T extends FaceoffRouteRecord<any, any, any, any>,
> = {
  [K in keyof T]: {
    type: K;
    data: T[K]['inputType'] extends undefined
      ? object
      : NonNullable<T[K]['inputType']>;
  };
}[keyof T];
/**
 * @ignore
 */
import { SketchyGame } from '..';
/**
 * @ignore
 */
import { EventsRecordToMartok } from '../../../sdk/GamesTypeFactory';
import { StrokeData } from './GameState';

export type DrawingDataEvent = {
  drawData: StrokeData;
  /** @precision int */
  drawRoundIndex: number;
};

export type ReplaceDrawingEvent = {
  drawData: StrokeData[];
  /** @precision int */
  drawRoundIndex: number;
};

export type SpeechTextEvent = {
  speechText?: string;
  speechData?: string[] | null;
  /** @precision int */
  drawRoundIndex: number;
};

export type UndoStrokeEvent = {
  strokeId: string;
  /** @precision int */
  drawRoundIndex: number;
};

/**
 * @expand
 */
export type SketchyEvents = EventsRecordToMartok<
  (typeof SketchyGame)['routes']
>;
janecakemaster commented 1 month ago

nothing has changed in the code it's just the upgrade to node 20 that's the difference

asarazan commented 1 month ago

Sounds good-- I'll try to reconstruct what I can to get a repro working. I no longer have access to any of the code and I'm a little foggy on my recollection.

I'm still missing FaceoffRouteRecord and SketchyGame if you're able to post here or email to aaron@sarazan.net it would definitely speed things up <3

janecakemaster commented 1 month ago
 * @ignore
 */
export type FaceoffRouteRecord<
  GameState extends StateExtension,
  Updates extends UpdatesExtension,
  Storage extends StorageExtension,
  Inputs extends InputExtension,
> = {
  [K in keyof Inputs]: RouteConfig<GameState, Updates, Storage, Inputs[K]>;
} & {
  startGame: RouteConfig<GameState, Updates, Storage, undefined>;
  stateUpdate?: RouteConfig<GameState, Updates, Storage, undefined>;
};
export const SketchyGame = SketchySdk.createGame(
  'sketchy',
  'Sketchy AF',
  createInitialGameState,
  endGameHandler,
  {
    startGame: startGameRoute,
    speechText: speechTextRoute,
    drawingData: drawingDataRoute,
    undoStroke: undoStrokeRoute,
    replaceDrawing: replaceDrawingRoute,
    readyUp: readyUpRoute,
    stateUpdate: stateUpdateRoute,
  }
);
  GameState extends StateExtension,
  Storage extends StorageExtension,
  Updates extends UpdatesExtension,
> {
  createGame<
    R extends FaceoffRouteRecord<GameState, Updates, Storage, any>,
    N extends string,
  >(
    id: N,
    name: string,
    createInitialGameState: (
      participants: PlayerObject<Storage>[],
      initiator: string
    ) => Promise<GameState>,
    handleEndGame: (state: GameState) => Promise<EndGameInfo>,
    routes: R
  ) {
    return {
      state: {} as GameState,
      storage: {} as Storage,
      updates: {} as Updates,
      id,
      name,
      createInitialGameState,
      handleEndGame,
      routes,
    };
  }

  createRoute<Input extends InputExtension | undefined = undefined>() {
    return new RouteBuilder<GameState, Updates, Storage, Input>();
  }
}