Skip to content

Commit

Permalink
Refactor MIME type to Media type (#213)
Browse files Browse the repository at this point in the history
The code changes involve renaming and refactoring all instances of 'MIME' to 'Media'. This includes variable names, function names, and file names. Additionally, the code now supports YAML format for marshalling and unmarshalling data. The media types are also guessed based on the input string.
  • Loading branch information
UnstoppableMango authored Jun 24, 2024
1 parent 31f67e4 commit a744382
Show file tree
Hide file tree
Showing 11 changed files with 87 additions and 37 deletions.
8 changes: 4 additions & 4 deletions packages/echo/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import * as tdl from '@unmango/tdl';
import * as cmd from './command';
import { name, version } from './package.json';

const mimeTypeOption = new Option('--type <TYPE>', 'The media type of the input.')
.choices(tdl.SUPPORTED_MIME_TYPES);
const mediaTypeOption = new Option('--type <TYPE>', 'The media type of the input.')
.choices(tdl.SUPPORTED_MEDIA_TYPES);

export const from = (program: Command): Command => {
program.command('from')
.description('Write back the protobuf data.')
.addOption(mimeTypeOption)
.addOption(mediaTypeOption)
.action(async (_) => {
const echo = new cmd.Echo();
const spec = await echo.from(Bun.stdin);
Expand All @@ -22,7 +22,7 @@ export const from = (program: Command): Command => {
export const gen = (program: Command): Command => {
program.command('gen')
.description('Also, write back the protobuf data.')
.addOption(mimeTypeOption)
.addOption(mediaTypeOption)
.action(async (_) => {
const echo = new cmd.Echo();
const spec = await echo.from(Bun.stdin);
Expand Down
2 changes: 1 addition & 1 deletion packages/tdl/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from './mime';
export * from './mediaType';
export * from './runner';
export * from './types';
4 changes: 2 additions & 2 deletions packages/tdl/mime.spec.ts → packages/tdl/mediaType.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Spec } from '@unmango/tdl-es';
import { describe, expect, it } from 'bun:test';
import fc from 'fast-check';
import { read, type SupportedMimeType } from './mime';
import { read, type SupportedMediaType } from './mediaType';

const arbSpec = () =>
fc.gen().map(g =>
Expand All @@ -15,7 +15,7 @@ const arbSpec = () =>
);

describe('read', () => {
it.each<SupportedMimeType>([
it.each<SupportedMediaType>([
'application/protobuf',
'application/x-protobuf',
'application/vnd.google.protobuf',
Expand Down
8 changes: 4 additions & 4 deletions packages/tdl/mime.ts → packages/tdl/mediaType.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import * as tdl from '@unmango/tdl-es';

export const SUPPORTED_MIME_TYPES = [
export const SUPPORTED_MEDIA_TYPES = [
'application/json',
'application/x-protobuf',
'application/protobuf',
'application/vnd.google.protobuf',
] as const;

export type SupportedMimeTypeTuple = typeof SUPPORTED_MIME_TYPES;
export type SupportedMimeType = SupportedMimeTypeTuple[number];
export type SupportedMediaTypeTuple = typeof SUPPORTED_MEDIA_TYPES;
export type SupportedMediaType = SupportedMediaTypeTuple[number];

export function read(data: Uint8Array, type?: SupportedMimeType): tdl.Spec {
export function read(data: Uint8Array, type?: SupportedMediaType): tdl.Spec {
switch (type) {
case 'application/json': {
const decoder = new TextDecoder();
Expand Down
12 changes: 6 additions & 6 deletions packages/uml2ts/command.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { SupportedMimeType } from '@unmango/tdl';
import type { SupportedMediaType } from '@unmango/tdl';
import { Spec } from '@unmango/tdl-es';
import { afterAll, beforeAll, describe, expect, it } from 'bun:test';
import fs from 'node:fs/promises';
Expand Down Expand Up @@ -32,16 +32,16 @@ beforeAll(async () => {
afterAll(ensureClean);

describe('gen', () => {
it.each<SupportedMimeType>([
it.each<SupportedMediaType>([
'application/protobuf',
'application/x-protobuf',
'application/vnd.google.protobuf',
])('should read %s data', async (mime) => {
])('should read %s data', async (mediaType) => {
const name = 'testType';
const spec = new Spec({ types: { [name]: {} } });
const bytes = spec.toBinary();

const proc = Bun.spawn([binPath, 'gen', '--type', mime], {
const proc = Bun.spawn([binPath, 'gen', '--type', mediaType], {
stdin: new Blob([bytes]),
});

Expand All @@ -53,9 +53,9 @@ describe('gen', () => {
const name = 'testType';
const spec = new Spec({ types: { [name]: {} } });
const json = spec.toJsonString();
const mime: SupportedMimeType = 'application/json';
const media: SupportedMediaType = 'application/json';

const proc = Bun.spawn([binPath, 'gen', '--type', mime], {
const proc = Bun.spawn([binPath, 'gen', '--type', media], {
stdin: Buffer.from(json, 'utf-8'),
});

Expand Down
2 changes: 1 addition & 1 deletion packages/uml2ts/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { gen as generate } from '@unmango/2ts';
import * as tdl from '@unmango/tdl';
import { ArrayBufferSink } from 'bun';

export async function gen(type?: tdl.SupportedMimeType): Promise<void> {
export async function gen(type?: tdl.SupportedMediaType): Promise<void> {
const buffer = await Bun.stdin.arrayBuffer();
const spec = tdl.read(new Uint8Array(buffer), type);
const sink = new ArrayBufferSink();
Expand Down
6 changes: 3 additions & 3 deletions packages/uml2ts/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import * as tdl from '@unmango/tdl';
import * as cmd from './command';
import { name, version } from './package.json';

const mimeTypeOption = new Option('--type <TYPE>', 'The media type of the input.')
.choices(tdl.SUPPORTED_MIME_TYPES);
const mediaTypeOption = new Option('--type <TYPE>', 'The media type of the input.')
.choices(tdl.SUPPORTED_MEDIA_TYPES);

export const gen = (program: Command): Command =>
program.command('gen')
.description('Generate typescript.')
.addOption(mimeTypeOption)
.addOption(mediaTypeOption)
.action((opts) => cmd.gen(opts.type));

export const program = (): Command =>
Expand Down
2 changes: 1 addition & 1 deletion pkg/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ require (
github.com/pulumi/pulumi/pkg/v3 v3.121.0
github.com/unstoppablemango/tdl/gen v0.0.18
google.golang.org/protobuf v1.34.2
gopkg.in/yaml.v3 v3.0.1
)

require (
Expand Down Expand Up @@ -125,7 +126,6 @@ require (
google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291 // indirect
google.golang.org/grpc v1.64.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools/v3 v3.5.1 // indirect
lukechampine.com/frand v1.4.2 // indirect
)
4 changes: 0 additions & 4 deletions pkg/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,8 @@ github.com/pulumi/appdash v0.0.0-20231130102222-75f619a67231 h1:vkHw5I/plNdTr435
github.com/pulumi/appdash v0.0.0-20231130102222-75f619a67231/go.mod h1:murToZ2N9hNJzewjHBgfFdXhZKjY3z5cYC1VXk+lbFE=
github.com/pulumi/esc v0.9.1 h1:HH5eEv8sgyxSpY5a8yePyqFXzA8cvBvapfH8457+mIs=
github.com/pulumi/esc v0.9.1/go.mod h1:oEJ6bOsjYlQUpjf70GiX+CXn3VBmpwFDxUTlmtUN84c=
github.com/pulumi/pulumi/pkg/v3 v3.120.0 h1:L2b8DiI4dQa+iRGXdbrMQl2AXUfnjP3siHEas6xPW84=
github.com/pulumi/pulumi/pkg/v3 v3.120.0/go.mod h1:ZLTGs4I1q5VXzjV5LLBLVIAfE811TMsSDFJaWs7WD4g=
github.com/pulumi/pulumi/pkg/v3 v3.121.0 h1:cLUQJYGJKfgCY0ubJo8dVwmsIm2WcgTprb9Orc/yiFg=
github.com/pulumi/pulumi/pkg/v3 v3.121.0/go.mod h1:aaRixfKOh4DhGtuDJcI56dTPkb7oJBgRgH1aMF1FzbU=
github.com/pulumi/pulumi/sdk/v3 v3.120.0 h1:KYtMkCmcSg4U+w41/Q0l3llKEodbfdyq6J0VMoEoVmY=
github.com/pulumi/pulumi/sdk/v3 v3.120.0/go.mod h1:/mQJPO+HehhoSJ9O3C6eUKAGeAr+4KSrbDhLsXHKldc=
github.com/pulumi/pulumi/sdk/v3 v3.121.0 h1:UsnFKIVOtJN/hQKPkWHL9cZktewPVQRbNUXbXQY/qrk=
github.com/pulumi/pulumi/sdk/v3 v3.121.0/go.mod h1:p1U24en3zt51agx+WlNboSOV8eLlPWYAkxMzVEXKbnY=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
Expand Down
6 changes: 3 additions & 3 deletions pkg/uml/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
)

type ConverterOptions struct {
MimeType *string
MediaType *string
}

type ConverterOption func(*ConverterOptions) error
Expand All @@ -19,9 +19,9 @@ type NewConverter[T any] interface {
RunnerFactory[T, Converter]
}

func WithMimeType(t string) ConverterOption {
func WithMediaType(t string) ConverterOption {
return func(opts *ConverterOptions) error {
opts.MimeType = &t
opts.MediaType = &t
return nil
}
}
70 changes: 62 additions & 8 deletions pkg/uml/marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,80 @@ import (
"encoding/json"
"fmt"
"mime"
"regexp"

"google.golang.org/protobuf/proto"
"gopkg.in/yaml.v3"
)

func Unmarshal(v string, b []byte, spec *Spec) error {
media, _, err := mime.ParseMediaType(v)
var (
jsonMatcher = regexp.MustCompile(`.*\.json`)
yamlMatcher = regexp.MustCompile(`.*\.ya?ml`)
)

func Marshal(typ string, spec *Spec) ([]byte, error) {
mediaType, err := parseMediaType(typ)
if err != nil {
return nil, err
}

switch mediaType {
case "application/json":
case "text/json":
return json.Marshal(spec)
case "application/x-protobuf":
case "application/protobuf":
case "application/vnd.google.protobuf":
return proto.Marshal(spec)
case "application/x-yaml":
case "application/yaml":
case "text/yaml":
return yaml.Marshal(spec)
}

return nil, fmt.Errorf("unsupported media type: %s", mediaType)
}

func Unmarshal(typ string, data []byte, spec *Spec) error {
mediaType, err := parseMediaType(typ)
if err != nil {
return err
}

switch media {
switch mediaType {
case "application/json":
err = json.Unmarshal(b, spec)
case "text/json":
return json.Unmarshal(data, spec)
case "application/x-protobuf":
case "application/protobuf":
case "application/vnd.google.protobuf":
err = proto.Unmarshal(b, spec)
default:
err = fmt.Errorf("unsupported media type: %s", media)
return proto.Unmarshal(data, spec)
case "application/x-yaml":
case "application/yaml":
case "text/yaml":
return yaml.Unmarshal(data, spec)
}

return fmt.Errorf("unsupported media type: %s", mediaType)
}

func GuessMediaType(x string) (string, error) {
if x == "stdin" {
return "application/protobuf", nil
}

return err
if yamlMatcher.MatchString(x) {
return "application/yaml", nil
}

if jsonMatcher.MatchString(x) {
return "application/json", nil
}

return "", fmt.Errorf("failed to guess media type for: %s", x)
}

func parseMediaType(x string) (string, error) {
mediaType, _, err := mime.ParseMediaType(x)
return mediaType, err
}

0 comments on commit a744382

Please sign in to comment.