Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions packages/samples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ This project has a collection of samples used to demonstrate and test various Ty

It is not published as an npm package.

Samples should teach a distinct TypeSpec concept or realistic workflow. Narrow protocol test
cases belong in the relevant package test suite instead of this collection.

Each sample directory has a `sample-config.yaml` containing a unique `title` and a
`description`. Set `playground: false` for samples that require multiple files or are not suitable
for the playground. A directory config uses `directory: true` and can provide a gallery `label`,
`order`, or an inherited `playground: false`.

```bash
npm run test # Check Samples match snapshots
npm run test:ci # run test same as CI
Expand Down
4 changes: 3 additions & 1 deletion packages/samples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"@typespec/best-practices": "workspace:^",
"@typespec/compiler": "workspace:^",
"@typespec/events": "workspace:^",
"@typespec/graphql": "workspace:^",
"@typespec/html-program-viewer": "workspace:^",
"@typespec/http": "workspace:^",
"@typespec/http-server-csharp": "workspace:^",
Expand All @@ -57,7 +58,8 @@
"@typespec/rest": "workspace:^",
"@typespec/sse": "workspace:^",
"@typespec/streams": "workspace:^",
"@typespec/versioning": "workspace:^"
"@typespec/versioning": "workspace:^",
"yaml": "catalog:"
},
"devDependencies": {
"@types/node": "catalog:",
Expand Down
3 changes: 3 additions & 0 deletions packages/samples/specs/authentication/sample-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
title: Authentication
description: Apply authentication schemes at service, interface, and operation scope.
playground: false
3 changes: 3 additions & 0 deletions packages/samples/specs/binary/sample-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
title: Binary data
description: Model binary request and response payloads.
playground: false
3 changes: 3 additions & 0 deletions packages/samples/specs/documentation/sample-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
title: Documentation
description: Add documentation to TypeSpec declarations and emitted API descriptions.
playground: false
46 changes: 46 additions & 0 deletions packages/samples/specs/emitters/graphql/main.tsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import "@typespec/graphql";

using GraphQL;

@schema
namespace PetStore;

/** A pet in the store. */
model Pet {
id: string;
name: string;
tag?: string;
status: PetStatus;
}

/** A pet's status in the store. */
enum PetStatus {
Available,
Pending,
Sold,
}

/** A toy that belongs to a pet. */
model Toy {
id: string;
name: string;
pet: Pet;
}

@query
op getPet(id: string): Pet | null;

@query
op listPets(status?: PetStatus, limit?: int32): Pet[];

@query
op getPetToys(petId: string): Toy[];

@mutation
op createPet(name: string, tag: string, status: PetStatus): Pet;

@mutation
op updatePet(id: string, name?: string, status?: PetStatus): Pet | null;

@mutation
op deletePet(id: string): boolean;
3 changes: 3 additions & 0 deletions packages/samples/specs/emitters/graphql/sample-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
title: GraphQL
description: Generate a GraphQL schema with queries, mutations, models, and enums.
order: 3
2 changes: 2 additions & 0 deletions packages/samples/specs/emitters/graphql/tspconfig.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
emit:
- "@typespec/graphql"
40 changes: 40 additions & 0 deletions packages/samples/specs/emitters/json-schema/main.tsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import "@typespec/json-schema";

using JsonSchema;

@jsonSchema
namespace Schemas;

model Person {
/** The person's first name. */
firstName: string;

/** The person's last name. */
lastName: string;

/** Age in years, which must be zero or greater. */
@minValue(0)
age: int32;

/** The person's address. */
address: Address;

/** The person's nicknames. */
@uniqueItems
nickNames?: string[];

/** Cars owned by the person. */
cars?: Car[];
}

model Address {
street: string;
city: string;
country: string;
}

model Car {
kind: "ev" | "ice";
brand: string;
`model`: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
title: JSON Schema
description: Generate JSON Schema documents from TypeSpec models and constraints.
order: 2
2 changes: 2 additions & 0 deletions packages/samples/specs/emitters/json-schema/tspconfig.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
emit:
- "@typespec/json-schema"
74 changes: 74 additions & 0 deletions packages/samples/specs/emitters/protobuf-kiosk/main.tsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import "@typespec/protobuf";

using Protobuf;

@package({
name: "kiosk",
})
namespace KioskExample;

@TypeSpec.Protobuf.service
interface Display {
/** Create a new kiosk and enroll it for sign display. */
createKiosk(...Kiosk): Kiosk;

/** List active kiosks. */
listKiosks(...WellKnown.Empty): {
@field(1) kiosks: Kiosk[];
};

/** Get a kiosk. */
getKiosk(@field(1) id: int32): Kiosk;

/** Delete a kiosk. */
deleteKiosk(@field(1) id: int32): void;

/** Create a new sign. */
createSign(...Sign): Sign;

/** List active signs. */
listSigns(...WellKnown.Empty): {
@field(1) signs: Sign[];
};

/** Get a sign. */
getSign(@field(1) id: int32): Sign;

/** Delete a sign. */
deleteSign(@field(1) id: int32): void;

/** Set a sign for display on one or more kiosks. */
setSignIdForKioskIds(@field(1) kioskIds: int32[], @field(2) signId: int32): void;

/** Get the sign that should be displayed on a kiosk. */
getSignIdForKioskId(@field(1) kioskId: int32): GetSignIdResponse;

/** Stream the signs that should be displayed on a kiosk. */
@stream(StreamMode.Out)
getSignIdsForKioskId(@field(1) kioskId: int32): GetSignIdResponse;
}

model Kiosk {
@field(1) id?: int32;
@field(2) name: string;
@field(3) size: ScreenSize;
@field(4) location: WellKnown.LatLng;
@field(5) createTime?: WellKnown.Timestamp;
}

model Sign {
@field(1) id?: int32;
@field(2) name: string;
@field(3) text: string;
@field(4) image: bytes;
@field(5) createTime?: WellKnown.Timestamp;
}

model ScreenSize {
@field(1) width: int32;
@field(2) height: int32;
}

model GetSignIdResponse {
@field(1) signId: int32;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
title: Protobuf kiosk
description: Generate Protocol Buffer service and message definitions for a kiosk system.
order: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
emit:
- "@typespec/protobuf"
3 changes: 3 additions & 0 deletions packages/samples/specs/emitters/sample-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
directory: true
label: Emitters
order: 3
3 changes: 3 additions & 0 deletions packages/samples/specs/encoded-names/sample-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
title: Encoded names
description: Customize declaration names for specific emitters.
playground: false
3 changes: 3 additions & 0 deletions packages/samples/specs/encoding/sample-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
title: Value encoding
description: Configure serialization formats for scalar values.
playground: false
44 changes: 44 additions & 0 deletions packages/samples/specs/getting-started/http-service/main.tsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import "@typespec/http";

using Http;

@service(#{ title: "Widget Service" })
namespace DemoService;

model Widget {
@visibility(Lifecycle.Read)
id: string;

weight: int32;
color: "red" | "blue";
}

@error
model Error {
code: int32;
message: string;
}

@route("/widgets")
@tag("Widgets")
interface Widgets {
/** List widgets. */
@get list(): Widget[] | Error;

/** Read a widget. */
@get read(@path id: Widget.id): Widget | Error;

/** Create a widget. */
@post create(@body widget: Widget): Widget | Error;

/** Update a widget. */
@patch update(@path id: Widget.id, @body widget: MergePatchUpdate<Widget>): Widget | Error;

/** Delete a widget. */
@delete delete(@path id: Widget.id): void | Error;

/** Analyze a widget. */
@route("{id}/analyze")
@post
analyze(@path id: Widget.id): string | Error;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
title: HTTP service
description: Build an HTTP service with routes, parameters, request bodies, and responses.
order: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
emit:
- "@typespec/openapi3"
linter:
extends:
- "@typespec/http/all"
26 changes: 26 additions & 0 deletions packages/samples/specs/getting-started/rest-framework/main.tsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import "@typespec/http";
import "@typespec/rest";

using Http;
using Rest;

@service(#{ title: "Widget Service" })
namespace DemoService;

model Widget {
@key id: string;
weight: int32;
color: "red" | "blue";
}

@error
model Error {
code: int32;
message: string;
}

interface WidgetService extends Resource.ResourceOperations<Widget, Error> {
@get
@route("customGet")
customGet(): Widget;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
title: REST framework
description: Use resource-oriented REST templates to define a service with less repetition.
order: 2
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
emit:
- "@typespec/openapi3"
linter:
extends:
- "@typespec/http/all"
3 changes: 3 additions & 0 deletions packages/samples/specs/getting-started/sample-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
directory: true
label: Getting Started
order: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
title: Advanced gRPC kiosk
description: Demonstrate a multi-file Protobuf-oriented kiosk service.
playground: false
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
title: Protobuf library
description: Build and consume reusable Protobuf declarations.
playground: false
3 changes: 3 additions & 0 deletions packages/samples/specs/init/sample-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
title: Project initialization
description: Show the service generated by the TypeSpec project initializer.
playground: false
38 changes: 38 additions & 0 deletions packages/samples/specs/language/api-versioning/main.tsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import "@typespec/http";
import "@typespec/rest";
import "@typespec/versioning";

using Http;
using Rest;
using Versioning;

@versioned(Versions)
@service(#{ title: "Widget Service" })
namespace DemoService;

enum Versions {
v1,
v2,
}

model Widget {
@key id: string;
weight: int32;
color: "red" | "blue";

@added(Versions.v2)
name: string;
}

@error
model Error {
code: int32;
message: string;
}

interface WidgetService extends Resource.ResourceOperations<Widget, Error> {
@added(Versions.v2)
@get
@route("customGet")
customGet(): Widget;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
title: API versioning
description: Evolve an API across versions with version-aware types and operations.
order: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
emit:
- "@typespec/openapi3"
Loading
Loading