Skip to content
New issue

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

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

Already on GitHub? # to your account

Special tags are wrong compiled in the SDK #1149

Closed
macols77 opened this issue Dec 12, 2024 · 3 comments
Closed

Special tags are wrong compiled in the SDK #1149

macols77 opened this issue Dec 12, 2024 · 3 comments
Assignees
Labels
bug Something isn't working

Comments

@macols77
Copy link

macols77 commented Dec 12, 2024

Bug Report

Summary

  • SDK Version: 4.2.0
  • Expected behavior: It should propagate my special tags on the sdk generation and create a relative import to it
  • Actual behavior: Add a dependency to the functional file with format "typia/lib/tags/LengthDivisibleBy" instead of using a relative path to my special tag.

Description

I've got some Special tags using typia (7.2.0) but the generated sdk has wrong dependencies. Basically, even if I declare those tags in the same controller file, the file generated with npx nestia sdk contain a imports like typia/lib/tags/LengthDivisibleBy or typia/lib/tags/RegexPattern when those are actually created by myself in the controller file. The sdk generator should copy my special tags too.

I've been reading your code and maybe the bug is here. Looks like you're always hardcoding the typia library path here

Code occuring the bug

export type RegexPattern<Value extends string> = typia.tags.TagBase<{
  target: 'string';
  kind: 'regexPattern';
  value: Value;
  validate: `RegExp(${Value}).test($input)`;
  schema: {};
}>;

export type LengthDivisibleBy<Value extends number> = typia.tags.TagBase<{
  target: 'string';
  kind: 'lengthDivisibleBy';
  value: Value;
  validate: `$input.length % ${Value} === 0`;
}>;

export type PubkeyInput = string &
  RegexPattern<'/^[0-9a-fA-F]+$/'> &
  LengthDivisibleBy<2>;

@Controller('v0/transaction')
export class TransactionController {
  constructor(private readonly transactionService: TransactionService) {}
  
  @TypedRoute.Get('user/:pubkey')
  async findTransactionsByUser(
    @TypedParam('pubkey')
    pubkey: PubkeyInput,
    @TypedQuery() query: FindTransactionsDto,
  ): Promise<PaginationResponse<Array<SerializeBigInt<TransactionResponse>>>> {
    const txs = await this.transactionService.findTransactionsByUser(
      hex.encode(toXOnly(hex.decode(pubkey))),
      query,
    );

    return {
      response: txs.response.map(serializeWithBigInt<TransactionResponse>),
      offset: txs.offset,
    };
  }
}

Compiled sdk

/**
 * @packageDocumentation
 * @module api.functional.v0.transaction.user
 * @nestia Generated by Nestia - https://github.com/samchon/nestia
 */
//================================================================
import type { IConnection, IPropagation } from "@nestia/fetcher";
import { PlainFetcher } from "@nestia/fetcher/lib/PlainFetcher";
import type { LengthDivisibleBy } from "typia/lib/tags/LengthDivisibleBy";
import type { RegexPattern } from "typia/lib/tags/RegexPattern";

import type { FindTransactionsDto } from "../../../../structures/FindTransactionsDto";
import type { PaginationResponseArraySerializeBigIntTransactionResponse } from "../../../../structures/PaginationResponseArraySerializeBigIntTransactionResponse";

export namespace findTransactionsByUser {
  export type Query = FindTransactionsDto;
  export type Output = IPropagation<
    {
      200: PaginationResponseArraySerializeBigIntTransactionResponse;
    },
    200
  >;

  export const METADATA = {
    method: "GET",
    path: "/v0/transaction/user/:pubkey",
    request: null,
    response: {
      type: "application/json",
      encrypted: false,
    },
    status: 200,
  } as const;

  export const path = (
    pubkey: string & RegexPattern<"/^[0-9a-fA-F]+$/"> & LengthDivisibleBy<2>,
    query: findTransactionsByUser.Query,
  ) => {
    const variables: URLSearchParams = new URLSearchParams();
    for (const [key, value] of Object.entries(query as any))
      if (undefined === value) continue;
      else if (Array.isArray(value))
        value.forEach((elem: any) => variables.append(key, String(elem)));
      else variables.set(key, String(value));
    const location: string = `/v0/transaction/user/${encodeURIComponent(pubkey?.toString() ?? "null")}`;
    return 0 === variables.size
      ? location
      : `${location}?${variables.toString()}`;
  };
}

Nestia SDK Config file

import { INestiaConfig } from '@nestia/sdk';

const config: INestiaConfig = {
  input: ['src/**/*.controller.ts', 'src/**/*.controller.internal.ts'],
  output: '../../packages/indexer-sdk/src',
  distribute: '../../packages/indexer-sdk',
  clone: true,
  primitive: false,
  propagate: true,
  swagger: {
    output: './swagger.json',
    servers: [
      {
        url: 'https://test.io',
        description: 'Production Server',
      },
    ],
  },
};

export default config;

tsconfig.json

{
  "extends": "../../tsconfig.json",
  "references": [
    {
      "path": "./tsconfig.test.json"
    }
  ],
  "compilerOptions": {
    "composite": true,
    // The following options are not required as they've been moved to the root tsconfig
    // "baseUrl": "./",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    // "incremental": true,
    // "skipLibCheck": true,
    "strictNullChecks": true,
    // "noImplicitAny": true,
    // "strictBindCallApply": true,
    // "forceConsistentCasingInFileNames": true,
    // "noFallthroughCasesInSwitch": true
    "moduleResolution": "nodenext",
    "module": "Node16",
    "declaration": true,
    "removeComments": true,
    "noImplicitAny": false,
    "strictBindCallApply": false,
    "allowSyntheticDefaultImports": true,
    "forceConsistentCasingInFileNames": false,
    "noFallthroughCasesInSwitch": false,
    "target": "ES2020",
    "sourceMap": true,
    "outDir": "./dist",
    "strict": true,
    "strictPropertyInitialization": false,
    "esModuleInterop": true,
    "plugins": [
      {
        "transform": "typia/lib/transform"
      },
      {
        "transform": "@nestia/core/lib/transform",
        "validate": "assert",
        "stringify": "assert"
      },
      {
        "transform": "@nestia/sdk/lib/transform"
      }
    ]
  },
  "include": ["src/**/*.ts", "typeorm/**/*.ts"],
  "exclude": [
    "./**/*.spec.ts",
    "./**/*.test.ts",
    "src/util/test.ts",
    "dist",
    "node_modules"
  ]
}
@macols77 macols77 changed the title Special tags are wrong compiled with the SDK Special tags are wrong compiled in the SDK Dec 12, 2024
@samchon samchon self-assigned this Dec 12, 2024
@samchon samchon added the bug Something isn't working label Dec 12, 2024
@samchon
Copy link
Owner

samchon commented Dec 12, 2024

I'll check it on Sunday. Thanks for bug reporting.

@samchon
Copy link
Owner

samchon commented Dec 14, 2024

Upgrade to v4.3.0 minor update, then this bug would be fixed.

It seems a little bit ugly, but this is the best way at right now.

I could not make a separate file due to how the generic type for the custom validation type should work.

export async function findTransactionsByUser(
  connection: IConnection,
  pubkey: string &
    TagBase<{
      target: "string";
      kind: "regexPattern";
      value: "/^[0-9a-fA-F]+$/";
      validate: "RegExp(/^[0-9a-fA-F]+$/).test($input)";
      exclusive: false;
      schema: {};
    }> &
    TagBase<{
      target: "string";
      kind: "lengthDivisibleBy";
      value: 2;
      validate: "$input.length % 2 === 0";
      exclusive: false;
    }>,
): Promise<void> {
  return PlainFetcher.fetch(connection, {
    ...findTransactionsByUser.METADATA,
    template: findTransactionsByUser.METADATA.path,
    path: findTransactionsByUser.path(pubkey),
  });
}

samchon added a commit that referenced this issue Dec 14, 2024
Fix #1149: clone mode with custom validator tag case.
@macols77
Copy link
Author

macols77 commented Dec 20, 2024

Great. Thank you very much

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
bug Something isn't working
Projects
No open projects
Status: Done
Development

No branches or pull requests

2 participants