본문으로 건너뛰기
cccskills
무료GitHub에 공개

skmtc-lang-typescript

The TypeScript target-language layer for Skmtc generators (@skmtc/lang-typescript): projection base factories, TsSnippet, the three register shapes, identifier kinds and the type-only import machinery, composition helpers, sanitization, TsFile render rules. Use ALONGSIDE skmtc-generator whenever a generator emits TypeScript. Headings are the template for other skmtc-lang-* skills.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

설치 방법 보기

포함된 파일(1)

  • SKILL.md8.7 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

The TypeScript layer (@skmtc/lang-typescript)

Read skmtc-generator first; you will normally have copied the skmtc-model skeleton (model generators — load that skill) or cloned @skmtc/gen-tanstack-query-fetch-zod (operation) — those are the worked examples. This skill carries the rules that aren't visible from imitation alone.

1. Declaring the language

The declaration is the import graph — no lang config field exists. src/base.ts imports a factory; the returned class extends TsSnippet, which carries the static lang Drivers read pre-construction.

import { toTsModelProjectionBase } from '@skmtc/lang-typescript'

export const MyBase = toTsModelProjectionBase<EnrichmentSchema>({
  id: denoJson.name,
  toIdentifierName({ refName }) { return decapitalize(camelCase(refName)) },
  toIdentifierType: () => ({ type: 'variable' }),
  toExportPath({ refName, enrichments, variant }) {
    const name = this.toIdentifierName({ refName, enrichments, variant })
    return `@/types/${name}.generated.ts`   // '@/' is basePath; always forward slashes
  },
  toEnrichmentSchema
})

Factories: toTsModelProjectionBase, toTsOasOperationProjectionBase (+ webhook/GQL variants). Snippets extend TsSnippet directly. Casing helpers (camelCase, capitalize, decapitalize) and toEndpointName come from @skmtc/core. An export path is @/ plus a forward-slash path relative to basePath; write it as a template literal, never with a path-library join, which would use the host's separator (backslashes on Windows) inside generated import text.

The veneers take two type parameters: EnrichmentType and ProjectionOptions, the caller options a peer passes as { options } on an insert (skmtc-generator §4). Declare the second to accept options; toIdentifierName / toExportPath then receive options and the instance stores it as this.options:

import { toTsModelProjectionBase } from '@skmtc/lang-typescript'

type ShapeOptions = { suffix: 'Input' | 'Output' }

export const MyBase = toTsModelProjectionBase<EnrichmentSchema, ShapeOptions>({
  id: denoJson.name,
  toIdentifierName({ refName, options }) { return `${camelCase(refName)}${options.suffix}` },
  toIdentifierType: () => ({ type: 'variable' }),
  toExportPath({ refName, enrichments, variant, options }) {
    const name = this.toIdentifierName({ refName, enrichments, variant, options })
    return `@/types/${name}.generated.ts`
  },
  toEnrichmentSchema
})

Consuming a peer that declares options needs nothing from this layer: this.insertModel(Peer, refName, { options }).

A projection consumable by peers via insertNormalizedModel also needs two statics: schemaToValueFn (your router) and createIdentifier.

2. The three register shapes

CallerCallDestination
Projectionthis.register(args)its own export file
Projectionthis.registerInto(path, args)explicit file
Snippetthis.register({ ...args, destinationPath })required — snippets own no file

Free functions for transform-level code: register(context, args); defineAndRegister(context, { identifier, value, destinationPath }) — no cache check (pair with context.findDefinition for the accumulator get-or-create idiom). Args: { imports?: Record<module, ImportNameArg[]>, reExports?, definitions?, custom? }. register creates the file on first write and drops self-imports, so register imports unconditionally — per-leaf registration (every snippet needing z registers { zod: ['z'] }) is the correct pattern, and merging is idempotent. An imports key spelled from the workspace root (@/, ./, /) is an export path; any other key (zod, types/y.ts) is a module specifier, written as it is.

3. Identifier kinds

TypeScript output has five entity kinds — TsEntityType = 'variable' | 'type' | 'class' | 'interface' | 'namespace' — factories createVariable(name, { typeName? }), createType, createClass, createInterface, createNamespace. No 'function' kind: a generated function is a variable whose value renders as an arrow function. The engine's identifier type is an opaque string; isTsEntityType narrows it to the five above. ContentSettings.identifier is the neutral IdentifierBase; toTsIdentifier(identifier) narrows it back to the TsIdentifier a reExports entry needs (a barrel: registerInto(barrelPath, { reExports: { [exportPath]: [toTsIdentifier(settings.identifier)] } })).

toIdentifierType is one lever with three effects: declaration keyword; block form (class/interface/namespace take no = value;); and whether consumers import it type-only (type and interface do — this is what keeps consumers compiling under verbatimModuleSyntax/TS1484, and you get it by choosing the kind, never by writing import syntax). File dedup keys on keyword+name, so class Foo + namespace Foo coexist (declaration merging); first write wins per slot.

4. Emitted-import rules

Concise forms per module: ['z'] (named), [{ default: 'invariant' }] (aliased/default), [{ name: 'User', type: 'type' }] (type-only). Sharp edge: only type: 'type' triggers type-only in the concise form — type: 'interface' does NOT; tag interfaces type: 'type'. Register against @/… export paths, where @/ is the workspace root. At render TsFile re-keys each module through settings.packages: same package → @/ from that package's root; another package → the innermost root's moduleName; no root → as written. A package file that imports a workspace-root path under no root throws at render.

5. Composition helpers

All Stringable, all deferring joins to render — use them instead of array.join whenever items are snippets (joining pre-renders and orphans provenance):

  • List — List.toObject/toArray/toParams/toLines/toKeyValue, List.fromKeys(record).toObject(fn), new List(values, { separator, bookends, skipEmpty }).
  • FunctionParameter({ typeDefinition, destructure, required, skipEmpty }) — one object, four readings: toString() (declaration), toInbound() (call site), toPropertyList(), hasProperty(name).
  • toPathTemplate('/users/{id}') → /users/${id}; toPathParams → /users/:id; PathParams bundles type + parameter + template.
  • keyValues, withDescription, handleKey, handlePropertyName; TsClass/TsHeritage for class syntax (TsHeritage registers its own heritage imports).

6. Sanitizing emitted names

Two different questions: sanitizeIdentifier(name) for binding names (export const <name>; repairs '2fa' → '_2fa', reserved → suffixed) vs sanitizePropertyName(name) for property keys / destructuring (returns a rename pair when repair is needed). Never hand-roll keyword lists.

7. Files

Render order: custom banner → re-exports → imports → definitions; first-wins per definition slot makes output order-independent. You almost never construct TsFile/TsImport/TsDefinition yourself — register and the Drivers do.

8. The contrast that matters

// WRONG: stored rendered text — z import never registers, refs duplicate
this.properties[key] = `z.string().optional()`
// RIGHT: stored snippet — imports settle, cache sees it, provenance holds
this.properties[key] = toMyValue({ schema: propSchema, required, destinationPath, context })

A cached peer name is a legitimate string — minding the two insert return shapes: this.responseName = definition.identifier.name from insertNormalizedModel, or .toName() off insertModel's Inserted handle. Modifier pipelines (applyModifiers-style) run inside toString(), never to build stored fields.

9. TypeScript pitfalls

SymptomFix
TS1484 in consumersIdentifier kind type/interface; concise imports need type: 'type'
Interface import emitted as valueTag it type: 'type' (known concise-form gap)
TS7022/7024 on recursive schemasSet settings.identifier.typeName (e.g. z.ZodType<X>) post-construction; the name stays stable
Provenance holes under some nodestoString must be a prototype method, never an arrow field
Doubled ?/modifiersOne owner: apply modifiers once, at the leaf's render

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Write, restructure, or review documentation — tutorials, how-to guides, reference pages, concept/explanation docs, API references, READMEs, changelogs, release notes, and troubleshooting guides. Distills documentation craft from Mintlify's guides (compiled from technical writers at Stripe, GitHub, Amplitude, and Anaconda), the Diátaxis framework (including the compass and per-type voice), the Google and Microsoft style guides, Every Page Is Page One, Write the Docs, and Docs for Developers: audience analysis, content-type selection, style and word-level rules, procedure writing, structure for humans and AI agents, code-example standards, page templates (templates.md), mechanical enforcement and llms.txt (mechanics.md), maintenance, and success metrics. Use this skill when the user asks to "write docs", "document this feature", "improve this page", "review these docs", "write a tutorial / how-to / reference page", "structure the docs", "write API documentation", "write a README / changelog", or when authoring any file under a `docs/` tree. For Skmtc docs specifically, this skill governs the *craft* (what makes the page good); the content split between skills, `llms.md`, and the docs tree is governed by `docs/skills/README.md`. Distinct from `skmtc-retro` (captures observations about work) and the `skmtc-*` operational skills (guide doing the work) — this skill guides writing *about* the work for readers.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

skmtc/skmtc192026년 10월 20일 업데이트

Understand what Skmtc is, how its engine works, and the architectural invariants — for agents building or extending infrastructure *around* Skmtc rather than authoring generators or running the CLI. Covers the three-phase pipeline, the host/Worker boundary, cross-generator coordination, the manifest, the attribution / gen-maps (provenance) subsystem, the package graph, the Deno and JSR platform, and the design decisions that make Skmtc behave unlike a typical codegen tool. Use this skill when the user asks "what is Skmtc", "how does the Skmtc engine work", "explain the Skmtc architecture", or is building platform infrastructure around Skmtc — a hosted generate API, a schema or generator registry, tracing or provenance tooling, a web app or SaaS that wraps the engine, or platform-level CI integration. This skill is the system mental model. It does NOT cover authoring generators (→ skmtc-generator), running CLI commands (→ skmtc-cli), or diagnosing broken runs (→ skmtc-debug).

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

skmtc/skmtc192026년 10월 20일 업데이트

skmtc-cli

무료

Use the Skmtc CLI to scaffold projects, install or clone generators from JSR, configure schema sources and enrichments, and produce code artifacts from an OpenAPI v3 or GraphQL SDL schema. Teaches the workspace mental model (`<root>/.skmtc/<project>/`, client.json, bundle, manifest) and the agent contract (strict text / strict JSON modes, exit codes, recipe errors, `agent-context` + `doctor`); the command surface itself is discovered from the binary — `skmtc --help`, `skmtc <cmd> -h` — rather than carried in this skill. Use this skill when the user asks to "run skmtc", "generate code from an OpenAPI schema", "install a skmtc generator", "scaffold a skmtc project", "watch a skmtc project", "configure enrichments", "publish a stack", "deploy to skmtc-hub" (the command is `publish`; there is no `deploy`), "skmtc in CI", or invokes any CLI subcommand. For *authoring* a generator package (Projections, Snippets, transform functions), defer to `skmtc-generator`. When something is broken (no output, wrong output, error messages, a failed bundle build), verify before proposing a fix: read the manifest and the parse issues, and reproduce the failure first.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

skmtc/skmtc192026년 10월 20일 업데이트

Diagnose failures in Skmtc sessions — no output, wrong output, error messages, failed bundle builds, parseIssues, "Registered definition mismatch", ref cycles, "Module not found" in generated code, or any other broken behavior. Applies across both CLI usage and generator authoring contexts. Use this skill when the user asks "why isn't my generator working", "no output for X", "wrong output", "what does this error mean", "manifest says X", "bundle failed", "INVALID_SCHEMA", "INVALID_DEPENDENCY_REF", "Registered definition mismatch", "Module not found" (in generated code), "ConfigValidationError", or reports any other Skmtc failure. This skill encodes a **verify-first epistemic stance** — read the manifest, check parseIssues, reproduce the failure before proposing fixes. Distinct from `skmtc-cli` and `skmtc-generator` which guide *doing*; this skill guides *diagnosing*.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

skmtc/skmtc192026년 10월 20일 업데이트

Author and edit Skmtc generators — packages that project an OpenAPI domain model into application code. Method: clone the nearest stock generator, then apply the engine rules imitation can't teach. Assumes zero prior Skmtc knowledge. Use when asked to "write a skmtc generator", "author/clone/customize gen-x", "add a field type", "change export paths", "add enrichment options", or when editing generator source. ALWAYS pair with the target language's skill (skmtc-lang-typescript).

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

skmtc/skmtc192026년 10월 20일 업데이트

The GraphQL pipeline for Skmtc generators — authoring generators whose input schema is GraphQL SDL rather than OpenAPI. Covers `toGqlOperationEntry`, `GqlOperation`, `synthesizeArgsObject` (mutation args -> object schema), the GQL enrichment routing (`[id][rootKind][fieldName][variant]` — two nested subject keys where OAS has path+method), the `to<Lang>GqlOperationProjectionBase` companion factories, and the `GeneratorKey` shape `id|rootKind|fieldName|variant`. Use this skill ALONGSIDE `skmtc-generator` whenever the schema source is GraphQL SDL or the task mentions "GraphQL", "SDL", "GqlOperation", "toGqlOperationEntry", or GraphQL query/mutation generators. Engine rules (producers, register/insert, the axioms) stay in `skmtc-generator`; this skill carries only what differs for GraphQL.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

skmtc/skmtc192026년 10월 20일 업데이트

skmtc의 스킬 모두 보기

이 스킬의 문제 신고