1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TypeSpecでscaffdogを利用する

Last updated at Posted at 2024-10-28

TypeSpecでscaffdogを利用する

背景

TypeSpecを利用する際に、SchemaとModelを分離したい気持ちが生じており、複数ファイルのテンプレートをVSCなどのテンプレートで利用せずにscaffdogを利用してファイルの生成速度をあげるための対応。

0. 想定しているdirectory構成

tree -L . -I node_modules
.
├── dockerfile
├── package-lock.json
├── package.json
├── scripts
│   └── sync
│       └── main.ts
├── src
│   ├── main.tsp       // monosilic dist用のファイル
│   ├── tspconfig.yaml // dist用config file
│   ├── blog           // model package
│   │   ├── model.tsp  // Model 
│   │   └── rotue.tsp  // Open API Schema
│   ├── rest-util
│   │   └── page.tsp
│   └── util
│       └── uuid.tsp
├── tsconfig.json
└── tsp-output
    └── @typespec
        └── openapi3

構成としては、src/{model_name}/model.tspにModelの内容を記載。
src/{model_name}/route.tspにOpenAPIのSchemaを記載

ex)src/blog/model.tsp
model Blog {
  @visibility("read")
  @key
  id: uint64;

  @visibility("create")
  title: blogTitle;
}

@minLength(1)
@maxLength(255)
scalar blogTitle extends string;

@withVisibility("create")
model CreateBlogContent {
  ...Blog;
}

op createBlogCotnent(dto: CreateBlogContent): Blog;

ex)src/blog/route.tsp
import "@typespec/http";
import "./model.tsp";
import "../rest-util/page.tsp";

using TypeSpec.Http;

@tag("blog")
@route("/blogs")
interface Blogs {
  create is createBlogCotnent;
  list(): Page<Blog>;
}

この記事で、ある程度の内容を書いてます。

1. scaffdogのinstallとinitialise

1-1. scaff dogのinstall

% npm install --save-dev scaffdog

1-2. scaff dogのinit

% npx scaffdog init

? Please enter a document name. scaff

Setup of scaffdog 🐶 is complete!

  ✔ .scaffdog/config.js
  ✔ .scaffdog/scaff.md

Now you can do scaffold by running `$ scaffdog generate`.

Please refer to the following documents and customize it.
https://scaff.dog/docs/templates

上記を実施すると、.scaffdogのdirectoryが作成され、2つのファイル(config.jsとscaff.md)が生成されていることが確認できます。

tree .scaffdog
.scaffdog
├── config.js
└── scaff.md

1 directory, 2 files

2. tspファイル用に生成ファイルをいじる

scaffdogでは、pascal caseやsnake caseなどのhelperなども準備されているため、
scaholdingのdocumentを生成します。
markdownの開始と終了については、qiitaの記事では省いておりますが、つけてください。

.scaffdog/scaff.md
---
name: 'scaff'
root: './src'
output: '**/*'
ignore: []
questions:
  name: 'Please enter name of model'
---


# Variables

- featurename: `{{ inputs.name | kebab }}`
- modelname: `{{ inputs.name | pascal }}`

# `{{ featurename }}/model.tsp`

markdown
/**
 * Generated by scaffdog
 * feature name is {{ featurename }}
 * created at {{ date "YYYY/MM/DD" }}
 **/

model {{ modelname }} {
}

# `{{ featurename }}/route.tsp`

/**
 * Generated by scaffdog
 * feature name is {{ featurename }}
 * created at {{ date "YYYY/MM/DD" }}
 **/
import "@typespec/http";
import "./model.tsp";

using TypeSpec.Http;

@tag("{{ inputs.name }}")
@route("/{{ inputs.name | kebab | plur }}")
interface {{ modelname | plur }} {
}

variablesに変数を置いています。

# {{ inputs.name | kebab | define 'filename' }}のようにした場合、defineしたファイルが正常にdistされないので注意してください。
(多分、内部の噛み合わせなのですが、中身まで見てない)

3. ファイルを生成してみる

% npx scaffdog generate
? Please select a document. scaff
ℹ Output destination directory: "./src"
? Please enter name of model user

🐶 Generated 2 files!

     ✔ src/user/model.tsp
     ✔ src/user/route.tsp
src/user/model.tsp
/**
 * Generated by scaffdog
 * feature name is user
 * created at 2024/10/28
 **/

model User {
}
src/user/route.tsp
/**
 * Generated by scaffdog
 * feature name is user
 * created at 2024/10/28
 **/
import "@typespec/http";
import "./model.tsp";

using TypeSpec.Http;

@tag("user")
@route("/users")
interface Users {
}

4. Templateを拡張して、distファイルにも追加する

4-0. 現状のmain.tsp

現状のsrc/main.tspについては、以下となっています。

src/main.tsp
import "@typespec/http";
import "@typespec/rest";
import "@typespec/openapi3";
import "./blog/route.tsp";

手動で、import "./user/route.tsp"を追加してもいいのですが、scaffdogを利用してもいいのですが、変更していきます。

4-1. main.tspのtemplateを作成

.scaffdog/.scaff.md
---
name: 'scaff'
root: './src'
output: 'src/*' // <- 変更
ignore: []
questions:
  name: 'Please enter name of model'
---
## 省略

# `main.tsp`

|```
{{ read output.abs }}
import "./{{ featurename }}/route.tsp";
|```

read output.absを利用してファイルの内部を読み込み最終行に追加していきます。

4-2. 生成

scaff dogはoverrideをする場合には、terminalで確認が可能となります。

% npx scaffdog generate
? Please select a document. scaff
ℹ Output destination directory: "./src"
? Please enter name of model user
⚠ Would you like to overwrite it?
("src/user/model.tsp") No
⚠ Would you like to overwrite it?
("src/user/route.tsp") No
⚠ Would you like to overwrite it? ("src/main.tsp") Yes


🐶 Generated 1 file! (2 skipped)

     ✔ src/main.tsp
     ⚠ src/user/model.tsp (skipped)
     ⚠ src/user/route.tsp (skipped)
src/main.tsp
import "@typespec/http";
import "@typespec/rest";
import "@typespec/openapi3";
import "./blog/route.tsp";
import "./user/route.tsp";
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?