Skip to content

Commit

Permalink
Jm/ext ts host (#117) Scale-65
Browse files Browse the repository at this point in the history
This adds typescript host support for extensions. Scale-65

---------

Signed-off-by: Jimmy Moore <[email protected]>
Signed-off-by: Shivansh Vij <[email protected]>
Co-authored-by: Shivansh Vij <[email protected]>
  • Loading branch information
jimmyaxod and ShivanshVij authored Dec 6, 2023
1 parent d726345 commit e41931f
Show file tree
Hide file tree
Showing 31 changed files with 1,947 additions and 12 deletions.
7 changes: 7 additions & 0 deletions config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import { Signature, New } from "@loopholelabs/scale-signature-interfaces";
import { V1BetaSchema } from "./scalefunc/scalefunc";
import { Extension } from "@loopholelabs/scale-extension-interfaces";

const envStringRegex = /[^A-Za-z0-9_]/;

Expand All @@ -38,6 +39,7 @@ export class Config<T extends Signature> {
stdout: Writer | undefined;
stderr: Writer | undefined;
rawOutput: boolean = false;
public extensions: Extension[] = [];

constructor(newSignature: New<T>) {
this.newSignature = newSignature;
Expand Down Expand Up @@ -87,6 +89,11 @@ export class Config<T extends Signature> {
return this;
}

public WithExtension(e: Extension): Config<T> {
this.extensions.push(e);
return this;
}

public WithStdout(writer: Writer): Config<T> {
this.stdout = writer
return this;
Expand Down
81 changes: 78 additions & 3 deletions extension/generator/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,17 @@
package generator

import (
"archive/tar"
"bytes"
"compress/gzip"
"encoding/hex"
"fmt"
"path"

"github.com/loopholelabs/scale/extension"
"github.com/loopholelabs/scale/extension/generator/golang"
"github.com/loopholelabs/scale/extension/generator/rust"
"github.com/loopholelabs/scale/extension/generator/typescript"
)

type GuestRegistryPackage struct {
Expand All @@ -45,8 +50,9 @@ type HostRegistryPackage struct {
}

type HostLocalPackage struct {
GolangFiles []File
TypescriptFiles []File
GolangFiles []File
TypescriptFiles []File
TypescriptPackage *bytes.Buffer
}

type Options struct {
Expand Down Expand Up @@ -157,7 +163,76 @@ func GenerateHostLocal(options *Options) (*HostLocalPackage, error) {
NewFile("go.mod", "go.mod", modfile),
}

typescriptTypes, err := typescript.GenerateTypesTranspiled(options.Extension, options.TypescriptPackageName, "types.js")
if err != nil {
return nil, err
}

typescriptHost, err := typescript.GenerateHostTranspiled(options.Extension, hashString, options.TypescriptPackageName, "index.js")
if err != nil {
return nil, err
}

packageJSON, err := typescript.GeneratePackageJSON(options.TypescriptPackageName, options.TypescriptPackageVersion)
if err != nil {
return nil, err
}

typescriptFiles := []File{
NewFile("types.ts", "types.ts", typescriptTypes.Typescript),
NewFile("types.js", "types.js", typescriptTypes.Javascript),
NewFile("types.js.map", "types.js.map", typescriptTypes.SourceMap),
NewFile("types.d.ts", "types.d.ts", typescriptTypes.Declaration),
NewFile("index.ts", "index.ts", typescriptHost.Typescript),
NewFile("index.js", "index.js", typescriptHost.Javascript),
NewFile("index.js.map", "index.js.map", typescriptHost.SourceMap),
NewFile("index.d.ts", "index.d.ts", typescriptHost.Declaration),
NewFile("package.json", "package.json", packageJSON),
}

typescriptBuffer := new(bytes.Buffer)
gzipTypescriptWriter := gzip.NewWriter(typescriptBuffer)
tarTypescriptWriter := tar.NewWriter(gzipTypescriptWriter)

var header *tar.Header
for _, file := range typescriptFiles {
header, err = tar.FileInfoHeader(file, file.Name())
if err != nil {
_ = tarTypescriptWriter.Close()
_ = gzipTypescriptWriter.Close()
return nil, fmt.Errorf("failed to create tar header for %s: %w", file.Name(), err)
}

header.Name = path.Join("package", header.Name)

err = tarTypescriptWriter.WriteHeader(header)
if err != nil {
_ = tarTypescriptWriter.Close()
_ = gzipTypescriptWriter.Close()
return nil, fmt.Errorf("failed to write tar header for %s: %w", file.Name(), err)
}
_, err = tarTypescriptWriter.Write(file.Data())
if err != nil {
_ = tarTypescriptWriter.Close()
_ = gzipTypescriptWriter.Close()
return nil, fmt.Errorf("failed to write tar data for %s: %w", file.Name(), err)
}
}

err = tarTypescriptWriter.Close()
if err != nil {
return nil, fmt.Errorf("failed to close tar writer: %w", err)
}

err = gzipTypescriptWriter.Close()
if err != nil {
return nil, fmt.Errorf("failed to close gzip writer: %w", err)
}

return &HostLocalPackage{
GolangFiles: golangFiles,
GolangFiles: golangFiles,
TypescriptFiles: typescriptFiles,
TypescriptPackage: typescriptBuffer,
}, nil

}
219 changes: 219 additions & 0 deletions extension/generator/typescript/generated.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
// Code generated by scale-signature 0.4.5, DO NOT EDIT.
// output: types

import { Encoder, Decoder, Kind } from "@loopholelabs/polyglot"

export class HttpConfig {
timeout: number;

/**
* @throws {Error}
*/
constructor (decoder?: Decoder) {
if (decoder) {
let err: Error | undefined;
try {
err = decoder.error();
} catch (_) {}
if (typeof err !== "undefined") {
throw err;
}
this.timeout = decoder.int32();
} else {
this.timeout = 60;
}
}

/**
* @throws {Error}
*/
encode (encoder: Encoder) {
encoder.int32(this.timeout);
}

/**
* @throws {Error}
*/
static decode (decoder: Decoder): HttpConfig | undefined {
if (decoder.null()) {
return undefined
}
return new HttpConfig(decoder);
}

/**
* @throws {Error}
*/
static encode_undefined (encoder: Encoder) {
encoder.null();
}
}

export class HttpResponse {
headers: Map<string, StringList>;

statusCode: number;

body: Uint8Array;

/**
* @throws {Error}
*/
constructor (decoder?: Decoder) {
if (decoder) {
let err: Error | undefined;
try {
err = decoder.error();
} catch (_) {}
if (typeof err !== "undefined") {
throw err;
}
this.headers = new Map<string, StringList>();
let headersSize = decoder.map(Kind.String, Kind.Any);
for (let i = 0; i < headersSize; i++) {
let key = decoder.string();
let val = StringList.decode(decoder);
if (typeof val !== "undefined") {
this.headers.set(key, val);
}
}
this.statusCode = decoder.int32();
this.body = decoder.uint8Array();
} else {
this.headers = new Map<string, StringList>();
this.statusCode = 0;
this.body = new Uint8Array(0);
}
}

/**
* @throws {Error}
*/
encode (encoder: Encoder) {
encoder.map(this.headers.size, Kind.String, Kind.Any);
this.headers.forEach((val, key) => {
encoder.string(key);
val.encode(encoder);
});
encoder.int32(this.statusCode);
encoder.uint8Array(this.body);
}

/**
* @throws {Error}
*/
static decode (decoder: Decoder): HttpResponse | undefined {
if (decoder.null()) {
return undefined
}
return new HttpResponse(decoder);
}

/**
* @throws {Error}
*/
static encode_undefined (encoder: Encoder) {
encoder.null();
}
}

export class StringList {
values: string[];

/**
* @throws {Error}
*/
constructor (decoder?: Decoder) {
if (decoder) {
let err: Error | undefined;
try {
err = decoder.error();
} catch (_) {}
if (typeof err !== "undefined") {
throw err;
}
const valuesSize = decoder.array(Kind.String);
this.values = new Array(valuesSize);
for (let i = 0; i < valuesSize; i += 1) {
this.values[i] = decoder.string();
}
} else {
this.values = [];
}
}

/**
* @throws {Error}
*/
encode (encoder: Encoder) {
const valuesLength = this.values.length;
encoder.array(valuesLength, Kind.String);
for (let i = 0; i < valuesLength; i += 1) {
encoder.string(this.values[i]);
}
}

/**
* @throws {Error}
*/
static decode (decoder: Decoder): StringList | undefined {
if (decoder.null()) {
return undefined
}
return new StringList(decoder);
}

/**
* @throws {Error}
*/
static encode_undefined (encoder: Encoder) {
encoder.null();
}
}

export class ConnectionDetails {
url: string;

/**
* @throws {Error}
*/
constructor (decoder?: Decoder) {
if (decoder) {
let err: Error | undefined;
try {
err = decoder.error();
} catch (_) {}
if (typeof err !== "undefined") {
throw err;
}
this.url = decoder.string();
} else {
this.url = "https://google.com";
}
}

/**
* @throws {Error}
*/
encode (encoder: Encoder) {
encoder.string(this.url);
}

/**
* @throws {Error}
*/
static decode (decoder: Decoder): ConnectionDetails | undefined {
if (decoder.null()) {
return undefined
}
return new ConnectionDetails(decoder);
}

/**
* @throws {Error}
*/
static encode_undefined (encoder: Encoder) {
encoder.null();
}
}

Loading

0 comments on commit e41931f

Please sign in to comment.