Skip to content

Commit

Permalink
refactor of spore-drive js/ts client (#255)
Browse files Browse the repository at this point in the history
  • Loading branch information
samyfodil authored Oct 17, 2024
1 parent a813d87 commit 35fc696
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 71 deletions.
9 changes: 9 additions & 0 deletions pkg/spore-drive/clients/js/gen/config/v1/config_connect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ import { MethodKind } from "@bufbuild/protobuf";
export const ConfigService = {
typeName: "config.v1.ConfigService",
methods: {
/**
* @generated from rpc config.v1.ConfigService.New
*/
new: {
name: "New",
I: Empty,
O: Config,
kind: MethodKind.Unary,
},
/**
* @generated from rpc config.v1.ConfigService.Load
*/
Expand Down
25 changes: 20 additions & 5 deletions pkg/spore-drive/clients/js/src/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,38 @@ import {
StringSlice,
BundleConfig,
Bundle,
SourceUpload
} from "../gen/config/v1/config_pb";

import { RPCClient } from "./ConfigClient";

async function* uploadAsyncIterator(stream: ReadableStream<Uint8Array>): AsyncIterable<SourceUpload> {
yield new SourceUpload({data:{case:"path", value:"/"}});

for await (const chunk of stream) {
yield new SourceUpload({data: {case:"chunk", value:chunk}});
}
}

// Main Config class
export class Config {
private client: RPCClient;
private source: Source;
private source?: string | ReadableStream<Uint8Array>;
private config?: ConfigMessage;

constructor(client: RPCClient, source: Source) {
this.client = client;
constructor(url: string, source?: string | ReadableStream<Uint8Array>) {
this.client = new RPCClient(url);
this.source = source;
}

async load(): Promise<void> {
this.config = await this.client.load(this.source);
async init(): Promise<void> {
if (typeof this.source === 'string') {
this.config = await this.client.load(new Source({ root: this.source, path: "/" }))
} else if (this.source instanceof ReadableStream) {
this.config = await this.client.upload(uploadAsyncIterator(this.source))
} else {
this.config = await this.client.new();
}
}

async free(): Promise<void> {
Expand Down
4 changes: 4 additions & 0 deletions pkg/spore-drive/clients/js/src/ConfigClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ export class RPCClient {
this.client = createPromiseClient(ConfigService, transport);
}

async new(): Promise<Config> {
return await this.client.new(new Empty());
}

async load(source: Source): Promise<Config> {
return await this.client.load(source);
}
Expand Down
14 changes: 9 additions & 5 deletions pkg/spore-drive/clients/js/src/Drive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,20 @@ export { TauBinarySource, TauLatest, TauVersion, TauUrl, TauPath };
export class Drive {
private client: RPCClient;
private drive?: DriveMessage;
private config: Config;
private tau?: TauBinarySource;

constructor(client: RPCClient) {
this.client = client;
constructor(url: string,config: Config,tau?: TauBinarySource) {
this.client = new RPCClient(url);
this.config = config;
this.tau = tau;
}

async init(config: Config, tau?: TauBinarySource): Promise<void> {
async init(): Promise<void> {
this.drive = await this.client.new(
new DriveRequest({
config: new ConfigMessage({ id: config.id() }),
tau: tau,
config: new ConfigMessage({ id: this.config.id() }),
tau: this.tau,
})
);
}
Expand Down
15 changes: 10 additions & 5 deletions pkg/spore-drive/clients/js/src/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import * as os from "os";
import { mkdtemp, rm } from "fs/promises";
import * as unzipper from "unzipper";
import * as yaml from "js-yaml";
import { Readable } from 'stream';


export const createConfig = async (config: Config) => {
// Set Cloud Domain
Expand Down Expand Up @@ -78,7 +80,6 @@ export const createConfig = async (config: Config) => {
describe("Config Class Integration Tests", () => {
let client: RPCClient;
let config: Config;
let source: Source;
let rpcUrl: string;
let mockServerProcess: ChildProcess;
let tempDir: string;
Expand Down Expand Up @@ -117,9 +118,8 @@ describe("Config Class Integration Tests", () => {

beforeEach(async () => {
tempDir = await mkdtemp(path.join(os.tmpdir(), "cloud-")); // Create a temporary directory
source = new Source({ root: tempDir, path: "/" });
config = new Config(client, source);
await config.load();
config = new Config(rpcUrl, tempDir);
await config.init();
});

afterEach(async () => {
Expand Down Expand Up @@ -174,7 +174,7 @@ describe("Config Class Integration Tests", () => {
expect(result).toBeDefined();
});

it("should download configuration bundle and verify it", async () => {
it("should download configuration bundle and verify it locally and through upload", async () => {
await createConfig(config);

const bundleIterator = await config.Download();
Expand Down Expand Up @@ -219,6 +219,11 @@ describe("Config Class Integration Tests", () => {
const yamlObject: any = yaml.load(yamlContent.toString());

expect(yamlObject.domain.root).toBe("test.com");

const config_from_zip = new Config(rpcUrl, Readable.toWeb(fs.createReadStream(zipPath)));
await config_from_zip.init();
expect(await config_from_zip.Cloud().Domain().Root().Get()).toBe("test.com");
await config_from_zip.free()
});

it("should set and get Swarm Key", async () => {
Expand Down
20 changes: 9 additions & 11 deletions pkg/spore-drive/clients/js/src/drive.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,8 @@ export const createConfig = async (

describe("Drive Class Integration Tests", () => {
let mock_client: PromiseClient<typeof MockSSHService>;
let config_client: ConfigClient;
let drive_client: DriveClient;
let drive: Drive;
let source: Source;
let config :Config;
let rpcUrl: string;
let mockServerProcess: ChildProcess;
let tempDir: string;
Expand Down Expand Up @@ -147,8 +145,6 @@ describe("Drive Class Integration Tests", () => {
});

mock_client = createPromiseClient(MockSSHService, transport);
config_client = new ConfigClient(rpcUrl);
drive_client = new DriveClient(rpcUrl);

touchFile("/tmp/faketau")
});
Expand All @@ -162,19 +158,21 @@ describe("Drive Class Integration Tests", () => {

beforeEach(async () => {
tempDir = await mkdtemp(path.join(os.tmpdir(), "cloud-")); // Create a temporary directory
source = new Source({ root: tempDir, path: "/" });
const config = new Config(config_client, source);
drive = new Drive(drive_client);
await config.load();
config = new Config(rpcUrl, tempDir);
await config.init();
await createConfig(mock_client, config);
await drive.init(config, TauPath("/tmp/faketau"));
await config.free();

drive = new Drive(rpcUrl,config, TauPath("/tmp/faketau"));
await drive.init();
});

afterEach(async () => {
await mock_client.free(new Hostname({ name: "host1" }));
await mock_client.free(new Hostname({ name: "host2" }));

await config.free();
await drive.free();

if (tempDir) {
await rm(tempDir, { recursive: true, force: true });
}
Expand Down
9 changes: 9 additions & 0 deletions pkg/spore-drive/config/service/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,15 @@ func (s *Service) Upload(ctx context.Context, stream *connect.ClientStream[pb.So
return connect.NewResponse(&pb.Config{Id: c.id}), nil
}

func (s *Service) New(context.Context, *connect.Request[pb.Empty]) (*connect.Response[pb.Config], error) {
cnf, err := s.newConfig(afero.NewMemMapFs(), "")
if err != nil {
return nil, fmt.Errorf("failed to create config: %w", err)
}

return connect.NewResponse(&pb.Config{Id: cnf.id}), nil
}

func (s *Service) Load(ctx context.Context, req *connect.Request[pb.Source]) (*connect.Response[pb.Config], error) {
root := req.Msg.GetRoot()
if root == "" {
Expand Down
1 change: 1 addition & 0 deletions pkg/spore-drive/proto/config/v1/config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ message Port {

// Service
service ConfigService {
rpc New(Empty) returns (Config);
rpc Load(Source) returns (Config);
rpc Upload(stream SourceUpload) returns (Config);
rpc Download(BundleConfig) returns (stream Bundle);
Expand Down
95 changes: 50 additions & 45 deletions pkg/spore-drive/proto/gen/config/v1/config.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 35fc696

Please # to comment.