-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(portal): integrate resource routing to portal (#235)
Update the portal code so that it aligns with the changes made in #220 Changelog: - [x] Create a `routing.ts` file containing the logic of parsing the Routes dynamic field. - [x] Add a function that finds if a path matches a route specified in the Routes DF. --------- Signed-off-by: giac-mysten <[email protected]> Co-authored-by: giac-mysten <[email protected]>
- Loading branch information
1 parent
be54071
commit ff4d6e0
Showing
9 changed files
with
197 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,6 @@ | |
} | ||
}, | ||
"routes": { | ||
"/path/*": "/index.html" | ||
"/path/*": "/file.svg" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// Copyright (c) Mysten Labs, Inc. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import { getRoutes, matchPathToRoute } from "./routing"; | ||
import { test, expect } from 'vitest'; | ||
import { SuiClient, getFullnodeUrl } from "@mysten/sui/client"; | ||
import { NETWORK } from "./constants"; | ||
|
||
const snakeSiteObjectId = '0x3e01b1b8bf0e54f7843596345faff146f1047e304410ed2eb85d5f67ad404206'; | ||
test.skip('getRoutes', async () => { | ||
// TODO: when you make sure get_routes fetches | ||
// the Routes dynamic field, mock the request. | ||
const rpcUrl = getFullnodeUrl(NETWORK); | ||
const client = new SuiClient({ url: rpcUrl }); | ||
const routes = await getRoutes(client, snakeSiteObjectId); | ||
console.log(routes) | ||
}); | ||
|
||
const routesExample = { | ||
routes_list: new Map<string, string>([ | ||
['/*', '/default.html'], | ||
['/somewhere/else', '/else.jpeg'], | ||
['/somewhere/else/*', '/star-else.gif'], | ||
['/path/to/*', '/somewhere.html'], | ||
]) | ||
}; | ||
|
||
const testCases = [ | ||
["/path/to/somewhere/", "/somewhere.html"], | ||
["/somewhere/else", '/else.jpeg'], | ||
["/", "/default.html"], | ||
["/somewhere", "/default.html"], | ||
["/somewhere/else/star", "/star-else.gif"], | ||
["/somewhere/else/", '/star-else.gif'], | ||
] | ||
|
||
testCases.forEach(([requestPath, expected]) => { | ||
test(`matchPathToRoute: "${requestPath}" -> "${expected}"`, () => { | ||
const match = matchPathToRoute(requestPath, routesExample) | ||
expect(match).toEqual(expected) | ||
}) | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// Copyright (c) Mysten Labs, Inc. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import { getFullnodeUrl, SuiClient, SuiObjectResponse } from "@mysten/sui/client"; | ||
import { Routes, } from "./types"; | ||
import { | ||
DynamicFieldStruct, | ||
RoutesStruct, | ||
} from "./bcs_data_parsing"; | ||
import { bcs, fromB64 } from "@mysten/bcs"; | ||
|
||
|
||
/** | ||
* Gets the Routes dynamic field of the site object. | ||
* Returns the extracted routes_list map to use for future requests, | ||
* and redirects the paths matched accordingly. | ||
* | ||
* @param siteObjectId - The ID of the site object. | ||
* @returns The routes list. | ||
*/ | ||
export async function getRoutes( | ||
client: SuiClient, siteObjectId: string | ||
): Promise<Routes | undefined> { | ||
const routesDF = await fetchRoutesDynamicField(client, siteObjectId); | ||
if (!routesDF.data) { | ||
console.warn("No routes dynamic field found for site object."); | ||
return; | ||
} | ||
const routesObj = await fetchRoutesObject(client, routesDF.data.objectId); | ||
const objectData = routesObj.data; | ||
if (objectData && objectData.bcs && objectData.bcs.dataType === "moveObject") { | ||
return parseRoutesData(objectData.bcs.bcsBytes); | ||
} | ||
throw new Error("Routes object data could not be fetched."); | ||
} | ||
|
||
/** | ||
* Fetches the dynamic field object for routes. | ||
* | ||
* @param client - The SuiClient instance. | ||
* @param siteObjectId - The ID of the site object. | ||
* @returns The dynamic field object for routes. | ||
*/ | ||
async function fetchRoutesDynamicField( | ||
client: SuiClient, siteObjectId: string | ||
): Promise<SuiObjectResponse> { | ||
return await client.getDynamicFieldObject({ | ||
parentId: siteObjectId, | ||
name: { type: "vector<u8>", value: "routes" }, | ||
}); | ||
} | ||
|
||
/** | ||
* Fetches the routes object using the dynamic field object ID. | ||
* | ||
* @param client - The SuiClient instance. | ||
* @param objectId - The ID of the dynamic field object. | ||
* @returns The routes object. | ||
*/ | ||
async function fetchRoutesObject(client: SuiClient, objectId: string): Promise<SuiObjectResponse> { | ||
return await client.getObject({ | ||
id: objectId, | ||
options: { showBcs: true } | ||
}); | ||
} | ||
|
||
/** | ||
* Parses the routes data from the BCS bytes. | ||
* | ||
* @param bcsBytes - The BCS bytes of the routes object. | ||
* @returns The parsed routes data. | ||
*/ | ||
function parseRoutesData(bcsBytes: string): Routes { | ||
const df = DynamicFieldStruct( | ||
// BCS declaration of the ROUTES_FIELD in site.move. | ||
bcs.vector(bcs.u8()), | ||
// The value of the df, i.e. the Routes Struct. | ||
RoutesStruct | ||
).parse(fromB64(bcsBytes)); | ||
|
||
return df.value as any as Routes; | ||
} | ||
|
||
/** | ||
* Matches the path to the appropriate route. | ||
* Path patterns in the routes list are sorted by length in descending order. | ||
* Then the first match is returned. | ||
* | ||
* @param path - The path to match. | ||
* @param routes - The routes to match against. | ||
*/ | ||
export function matchPathToRoute(path: string, routes: Routes) { | ||
// TODO: improve this using radix trees. | ||
const res = Array | ||
.from(routes.routes_list.entries()) | ||
.filter(([pattern, _]) => new RegExp(`^${pattern.replace('*', '.*')}$`).test(path)) | ||
.reduce((a, b) => a[0].length >= b[0].length ? a : b) | ||
return res ? res[1] : undefined; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters