feat(client): add function alias support (#7)
* feat(client): add function alias support * fix(client): username in aliased url
This commit is contained in:
parent
0503bbe66a
commit
3b11d468a8
1
.gitignore
vendored
1
.gitignore
vendored
@ -40,3 +40,4 @@ Thumbs.db
|
||||
|
||||
# Next.js
|
||||
.next
|
||||
*.local
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# The fal-serverless JS Client
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
@ -22,7 +22,7 @@ It also handle platform differences, so it work seamlessly across different JS r
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> Make sure you followed the [fal-serverless getting started]() so you get your credentials and register your functions.
|
||||
> Make sure you followed the [fal-serverless getting started](https://docs.fal.ai/fal-serverless/quickstart) so you get your credentials and register your functions.
|
||||
|
||||
1. First you need to configure your credentials:
|
||||
|
||||
|
||||
@ -1,57 +1,69 @@
|
||||
import styles from './index.module.css';
|
||||
import * as fal from '@fal-ai/serverless-client';
|
||||
|
||||
fal.config({
|
||||
credentials: {
|
||||
userId: '',
|
||||
keyId: '',
|
||||
keySecret: '',
|
||||
},
|
||||
});
|
||||
import { getJoke } from '../services/getJoke';
|
||||
|
||||
export async function getServerSideProps(context) {
|
||||
console.log('About to call a fal serverless function from NodeJS');
|
||||
const result = await fal.run(
|
||||
'e300f60b-4a7c-44cd-871d-bea588ef43d6/jokes/add',
|
||||
{
|
||||
input: {
|
||||
joke: 'fal serverless is cool, so the joke is on you!',
|
||||
try {
|
||||
const result = await getJoke();
|
||||
return {
|
||||
props: {
|
||||
...result,
|
||||
},
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
props: {
|
||||
error: error.message,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function Error(props) {
|
||||
if (!props.error) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<div
|
||||
className="p-4 mb-4 text-sm text-red-800 rounded bg-red-50 dark:bg-gray-800 dark:text-red-400"
|
||||
role="alert"
|
||||
>
|
||||
<span className="font-medium">Error</span> {props.error}
|
||||
</div>
|
||||
);
|
||||
console.log(result);
|
||||
const random = await fal.run(
|
||||
'e300f60b-4a7c-44cd-871d-bea588ef43d6/jokes/get',
|
||||
{
|
||||
method: 'get',
|
||||
}
|
||||
);
|
||||
console.log(random);
|
||||
return {
|
||||
props: {
|
||||
random,
|
||||
result,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function Index(props) {
|
||||
const handleClick = async (e) => {
|
||||
e.preventDefault();
|
||||
try {
|
||||
const joke = await getJoke();
|
||||
console.log(joke);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div className="container mx-auto p-4">
|
||||
<h1 className="text-4xl font-bold mb-8">
|
||||
Hello <code>fal serverless</code>
|
||||
</h1>
|
||||
<p className="text-lg">
|
||||
This page can access <strong>fal serverless</strong> functions when
|
||||
it's rendering.
|
||||
</p>
|
||||
<p>
|
||||
Added joke with success?{' '}
|
||||
<strong>{props.result.success.toString()}</strong>
|
||||
</p>
|
||||
<p>
|
||||
Joke <strong>{props.random.joke}</strong>
|
||||
</p>
|
||||
<div className="min-h-screen dark:bg-gray-900 dark:text-white bg-white text-black">
|
||||
<main className="flex flex-col items-center justify-center w-full flex-1 px-20 py-10">
|
||||
<h1 className="text-4xl font-bold mb-8">
|
||||
Hello <code>fal-serverless</code>
|
||||
</h1>
|
||||
<p className="text-lg mb-10">
|
||||
This page can access <strong>fal-serverless</strong> functions when
|
||||
it's rendering.
|
||||
</p>
|
||||
<Error error={props.error} />
|
||||
|
||||
<button
|
||||
onClick={handleClick}
|
||||
className="mt-4 bg-blue-500 hover:bg-blue-700 text-white font-bold text-xl py-4 px-8 mx-auto rounded focus:outline-none focus:shadow-outline"
|
||||
>
|
||||
Get Joke
|
||||
</button>
|
||||
|
||||
<p className="mt-10">
|
||||
Here's a joke: <strong>{props.joke}</strong>
|
||||
</p>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -18,12 +18,10 @@ fal.config({
|
||||
export async function generateImage(
|
||||
input: GenerateImageInput
|
||||
): Promise<ImageDataUri> {
|
||||
const result = await fal.run(
|
||||
'a51c0ca0-9011-4ff0-8dc1-2ac0b42a9fd0/generate',
|
||||
{
|
||||
input,
|
||||
}
|
||||
);
|
||||
const result = await fal.run('a51c0ca0-9011-4ff0-8dc1-2ac0b42a9fd0', {
|
||||
path: '/generate',
|
||||
input,
|
||||
});
|
||||
const data = result['raw_data'];
|
||||
return `data:image/jpg;base64,${data}`;
|
||||
}
|
||||
|
||||
18
apps/demo-app/services/getJoke.ts
Normal file
18
apps/demo-app/services/getJoke.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import * as fal from '@fal-ai/serverless-client';
|
||||
|
||||
fal.config({
|
||||
host: 'gateway.alpha.fal.ai',
|
||||
credentials: {
|
||||
userId: process.env.FAL_USER_ID || '',
|
||||
keyId: process.env.FAL_KEY_ID || '',
|
||||
keySecret: process.env.FAL_KEY_SECRET || '',
|
||||
},
|
||||
});
|
||||
|
||||
export type GetJokeInput = {
|
||||
language?: string;
|
||||
};
|
||||
|
||||
export function getJoke(input?: GetJokeInput): Promise<{ joke: string }> {
|
||||
return fal.run('fastapi_get_joke', { input });
|
||||
}
|
||||
@ -12,7 +12,7 @@ export type Config = {
|
||||
export type RequiredConfig = Required<Config>;
|
||||
|
||||
const DEFAULT_CONFIG: Partial<Config> = {
|
||||
host: 'https://gateway.shark.fal.ai',
|
||||
host: 'gateway.shark.fal.ai',
|
||||
};
|
||||
|
||||
let configuration: RequiredConfig | undefined = undefined;
|
||||
@ -33,7 +33,7 @@ export function config(config: Config) {
|
||||
*/
|
||||
export function getConfig(): RequiredConfig {
|
||||
if (typeof configuration === 'undefined') {
|
||||
throw new Error('You must configure fal serverless first.');
|
||||
throw new Error('You must configure fal-serverless first.');
|
||||
}
|
||||
return configuration;
|
||||
}
|
||||
|
||||
28
libs/client/src/function.spec.ts
Normal file
28
libs/client/src/function.spec.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { randomUUID } from 'crypto';
|
||||
import { config, getConfig } from './config';
|
||||
import { buildUrl } from './function';
|
||||
|
||||
config({
|
||||
host: 'gateway.alpha.fal.ai',
|
||||
credentials: {
|
||||
userId: 'github|123456',
|
||||
keyId: 'a91ff3ca-71bc-4c8c-b400-859f6cbe804d',
|
||||
keySecret: '0123456789abcdfeghijklmnopqrstuv',
|
||||
},
|
||||
});
|
||||
|
||||
describe('The function test suite', () => {
|
||||
it('should build the URL with a function UUIDv4', () => {
|
||||
const { credentials } = getConfig();
|
||||
const id = randomUUID();
|
||||
const url = buildUrl(id);
|
||||
expect(url).toMatch(`trigger/${credentials.userId}/${id}`);
|
||||
});
|
||||
|
||||
it('should build the URL with a function alias', () => {
|
||||
const { host } = getConfig();
|
||||
const alias = 'some-alias';
|
||||
const url = buildUrl(alias);
|
||||
expect(url).toMatch(`${alias}.${host}`);
|
||||
});
|
||||
});
|
||||
@ -1,12 +1,22 @@
|
||||
import fetch from 'cross-fetch';
|
||||
import { getConfig } from './config';
|
||||
import { getUserAgent, isBrowser } from './runtime';
|
||||
import { isUUIDv4 } from './utils';
|
||||
|
||||
/**
|
||||
* The function input and other configuration when running
|
||||
* the function, such as the HTTP method to use.
|
||||
*/
|
||||
type RunOptions<Input> = {
|
||||
/**
|
||||
* The path to the function, if any. Defaults to `/`.
|
||||
*/
|
||||
readonly path?: string;
|
||||
|
||||
/**
|
||||
* The function input. It will be submitted either as query params
|
||||
* or the body payload, depending on the `method`.
|
||||
*/
|
||||
readonly input?: Input;
|
||||
|
||||
/**
|
||||
@ -15,6 +25,35 @@ type RunOptions<Input> = {
|
||||
readonly method?: 'get' | 'post' | 'put' | 'delete';
|
||||
};
|
||||
|
||||
/**
|
||||
* Builds the final url to run the function based on its `id` or alias and
|
||||
* a the options from `RunOptions<Input>`.
|
||||
*
|
||||
* @private
|
||||
* @param id the function id or alias
|
||||
* @param options the run options
|
||||
* @returns the final url to run the function
|
||||
*/
|
||||
export function buildUrl<Input>(
|
||||
id: string,
|
||||
options: RunOptions<Input> = {}
|
||||
): string {
|
||||
const { credentials, host } = getConfig();
|
||||
const method = (options.method ?? 'post').toLowerCase();
|
||||
const path = options.path ?? '';
|
||||
const params =
|
||||
method === 'get' ? new URLSearchParams(options.input ?? {}) : undefined;
|
||||
let queryParams = '';
|
||||
if (params) {
|
||||
queryParams = `?${params.toString()}`;
|
||||
}
|
||||
if (isUUIDv4(id)) {
|
||||
return `https://${host}/trigger/${credentials.userId}/${id}/${path}${queryParams}`;
|
||||
}
|
||||
const userId = credentials.userId.replace(/github\|/g, '');
|
||||
return `https://${userId}-${id}.${host}/${path}${queryParams}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a fal serverless function identified by its `id`.
|
||||
* TODO: expand documentation and provide examples
|
||||
@ -24,31 +63,32 @@ type RunOptions<Input> = {
|
||||
*/
|
||||
export async function run<Input, Output>(
|
||||
id: string,
|
||||
options?: RunOptions<Input>
|
||||
options: RunOptions<Input> = {}
|
||||
): Promise<Output> {
|
||||
const { credentials, host } = getConfig();
|
||||
const { credentials } = getConfig();
|
||||
const method = (options.method ?? 'post').toLowerCase();
|
||||
const params =
|
||||
method === 'get' ? new URLSearchParams(options.input ?? {}).toString() : '';
|
||||
const userAgent = isBrowser ? {} : { 'User-Agent': getUserAgent() };
|
||||
const response = await fetch(
|
||||
`${host}/trigger/${credentials.userId}/${id}${params}`,
|
||||
{
|
||||
method,
|
||||
headers: {
|
||||
'X-Fal-Key-Id': credentials.keyId,
|
||||
'X-Fal-Key-Secret': credentials.keySecret,
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
...userAgent,
|
||||
},
|
||||
mode: 'cors',
|
||||
body:
|
||||
method !== 'get' && options.input
|
||||
? JSON.stringify(options.input)
|
||||
: null,
|
||||
}
|
||||
);
|
||||
const response = await fetch(buildUrl(id, options), {
|
||||
method,
|
||||
headers: {
|
||||
'X-Fal-Key-Id': credentials.keyId,
|
||||
'X-Fal-Key-Secret': credentials.keySecret,
|
||||
'Content-Type': 'application/json',
|
||||
...userAgent,
|
||||
},
|
||||
mode: 'cors',
|
||||
body:
|
||||
method !== 'get' && options.input
|
||||
? JSON.stringify(options.input)
|
||||
: undefined,
|
||||
});
|
||||
|
||||
const { status, statusText } = response;
|
||||
if (status < 200 || status >= 300) {
|
||||
// TODO better error type so handlers can differentiate
|
||||
throw new Error(statusText);
|
||||
}
|
||||
|
||||
// TODO move this elsewhere so it can be reused by websocket impl too
|
||||
const contentType = response.headers.get('Content-Type');
|
||||
if (contentType?.includes('application/json')) {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
export type { Credentials } from './config';
|
||||
export { config } from './config';
|
||||
export type { FunctionExecution, ProgressEvent } from './function';
|
||||
export type { Credentials } from './config';
|
||||
export { run } from './function';
|
||||
export type { FunctionExecution, ProgressEvent } from './function';
|
||||
|
||||
14
libs/client/src/utils.spec.ts
Normal file
14
libs/client/src/utils.spec.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { randomUUID } from 'crypto';
|
||||
import { isUUIDv4 } from './utils';
|
||||
|
||||
describe('The utils test suite', () => {
|
||||
it('should match a valid v4 uuid', () => {
|
||||
const id = randomUUID();
|
||||
expect(isUUIDv4(id)).toBe(true);
|
||||
});
|
||||
|
||||
it('should not match invalid v4 id', () => {
|
||||
const id = 'e726b886-e2c2-11ed-b5ea-0242ac120002';
|
||||
expect(isUUIDv4(id)).toBe(false);
|
||||
});
|
||||
});
|
||||
8
libs/client/src/utils.ts
Normal file
8
libs/client/src/utils.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export function isUUIDv4(id: string): boolean {
|
||||
return (
|
||||
typeof id === 'string' &&
|
||||
id.length === 36 &&
|
||||
id[14] === '4' &&
|
||||
['8', '9', 'a', 'b'].includes(id[19])
|
||||
);
|
||||
}
|
||||
231
package-lock.json
generated
231
package-lock.json
generated
@ -3179,6 +3179,126 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-android-arm-eabi": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.1.1.tgz",
|
||||
"integrity": "sha512-qnFCx1kT3JTWhWve4VkeWuZiyjG0b5T6J2iWuin74lORCupdrNukxkq9Pm+Z7PsatxuwVJMhjUoYz7H4cWzx2A==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-android-arm64": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-13.1.1.tgz",
|
||||
"integrity": "sha512-eCiZhTzjySubNqUnNkQCjU3Fh+ep3C6b5DCM5FKzsTH/3Gr/4Y7EiaPZKILbvnXmhWtKPIdcY6Zjx51t4VeTfA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-darwin-arm64": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.1.1.tgz",
|
||||
"integrity": "sha512-9zRJSSIwER5tu9ADDkPw5rIZ+Np44HTXpYMr0rkM656IvssowPxmhK0rTreC1gpUCYwFsRbxarUJnJsTWiutPg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-darwin-x64": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.1.1.tgz",
|
||||
"integrity": "sha512-qWr9qEn5nrnlhB0rtjSdR00RRZEtxg4EGvicIipqZWEyayPxhUu6NwKiG8wZiYZCLfJ5KWr66PGSNeDMGlNaiA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-freebsd-x64": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.1.1.tgz",
|
||||
"integrity": "sha512-UwP4w/NcQ7V/VJEj3tGVszgb4pyUCt3lzJfUhjDMUmQbzG9LDvgiZgAGMYH6L21MoyAATJQPDGiAMWAPKsmumA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-linux-arm-gnueabihf": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.1.1.tgz",
|
||||
"integrity": "sha512-CnsxmKHco9sosBs1XcvCXP845Db+Wx1G0qouV5+Gr+HT/ZlDYEWKoHVDgnJXLVEQzq4FmHddBNGbXvgqM1Gfkg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-linux-arm64-gnu": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.1.1.tgz",
|
||||
"integrity": "sha512-JfDq1eri5Dif+VDpTkONRd083780nsMCOKoFG87wA0sa4xL8LGcXIBAkUGIC1uVy9SMsr2scA9CySLD/i+Oqiw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-linux-arm64-musl": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.1.1.tgz",
|
||||
"integrity": "sha512-GA67ZbDq2AW0CY07zzGt07M5b5Yaq5qUpFIoW3UFfjOPgb0Sqf3DAW7GtFMK1sF4ROHsRDMGQ9rnT0VM2dVfKA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-linux-x64-gnu": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.1.1.tgz",
|
||||
@ -3209,6 +3329,51 @@
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-win32-arm64-msvc": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.1.1.tgz",
|
||||
"integrity": "sha512-pzUHOGrbgfGgPlOMx9xk3QdPJoRPU+om84hqVoe6u+E0RdwOG0Ho/2UxCgDqmvpUrMab1Deltlt6RqcXFpnigQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-win32-ia32-msvc": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.1.1.tgz",
|
||||
"integrity": "sha512-WeX8kVS46aobM9a7Xr/kEPcrTyiwJqQv/tbw6nhJ4fH9xNZ+cEcyPoQkwPo570dCOLz3Zo9S2q0E6lJ/EAUOBg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-win32-x64-msvc": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.1.1.tgz",
|
||||
"integrity": "sha512-mVF0/3/5QAc5EGVnb8ll31nNvf3BWpPY4pBb84tk+BfQglWLqc5AC9q1Ht/YMWiEgs8ALNKEQ3GQnbY0bJF2Gg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
@ -29665,6 +29830,54 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@next/swc-android-arm-eabi": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.1.1.tgz",
|
||||
"integrity": "sha512-qnFCx1kT3JTWhWve4VkeWuZiyjG0b5T6J2iWuin74lORCupdrNukxkq9Pm+Z7PsatxuwVJMhjUoYz7H4cWzx2A==",
|
||||
"optional": true
|
||||
},
|
||||
"@next/swc-android-arm64": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-13.1.1.tgz",
|
||||
"integrity": "sha512-eCiZhTzjySubNqUnNkQCjU3Fh+ep3C6b5DCM5FKzsTH/3Gr/4Y7EiaPZKILbvnXmhWtKPIdcY6Zjx51t4VeTfA==",
|
||||
"optional": true
|
||||
},
|
||||
"@next/swc-darwin-arm64": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.1.1.tgz",
|
||||
"integrity": "sha512-9zRJSSIwER5tu9ADDkPw5rIZ+Np44HTXpYMr0rkM656IvssowPxmhK0rTreC1gpUCYwFsRbxarUJnJsTWiutPg==",
|
||||
"optional": true
|
||||
},
|
||||
"@next/swc-darwin-x64": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.1.1.tgz",
|
||||
"integrity": "sha512-qWr9qEn5nrnlhB0rtjSdR00RRZEtxg4EGvicIipqZWEyayPxhUu6NwKiG8wZiYZCLfJ5KWr66PGSNeDMGlNaiA==",
|
||||
"optional": true
|
||||
},
|
||||
"@next/swc-freebsd-x64": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.1.1.tgz",
|
||||
"integrity": "sha512-UwP4w/NcQ7V/VJEj3tGVszgb4pyUCt3lzJfUhjDMUmQbzG9LDvgiZgAGMYH6L21MoyAATJQPDGiAMWAPKsmumA==",
|
||||
"optional": true
|
||||
},
|
||||
"@next/swc-linux-arm-gnueabihf": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.1.1.tgz",
|
||||
"integrity": "sha512-CnsxmKHco9sosBs1XcvCXP845Db+Wx1G0qouV5+Gr+HT/ZlDYEWKoHVDgnJXLVEQzq4FmHddBNGbXvgqM1Gfkg==",
|
||||
"optional": true
|
||||
},
|
||||
"@next/swc-linux-arm64-gnu": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.1.1.tgz",
|
||||
"integrity": "sha512-JfDq1eri5Dif+VDpTkONRd083780nsMCOKoFG87wA0sa4xL8LGcXIBAkUGIC1uVy9SMsr2scA9CySLD/i+Oqiw==",
|
||||
"optional": true
|
||||
},
|
||||
"@next/swc-linux-arm64-musl": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.1.1.tgz",
|
||||
"integrity": "sha512-GA67ZbDq2AW0CY07zzGt07M5b5Yaq5qUpFIoW3UFfjOPgb0Sqf3DAW7GtFMK1sF4ROHsRDMGQ9rnT0VM2dVfKA==",
|
||||
"optional": true
|
||||
},
|
||||
"@next/swc-linux-x64-gnu": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.1.1.tgz",
|
||||
@ -29677,6 +29890,24 @@
|
||||
"integrity": "sha512-CM9xnAQNIZ8zf/igbIT/i3xWbQZYaF397H+JroF5VMOCUleElaMdQLL5riJml8wUfPoN3dtfn2s4peSr3azz/g==",
|
||||
"optional": true
|
||||
},
|
||||
"@next/swc-win32-arm64-msvc": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.1.1.tgz",
|
||||
"integrity": "sha512-pzUHOGrbgfGgPlOMx9xk3QdPJoRPU+om84hqVoe6u+E0RdwOG0Ho/2UxCgDqmvpUrMab1Deltlt6RqcXFpnigQ==",
|
||||
"optional": true
|
||||
},
|
||||
"@next/swc-win32-ia32-msvc": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.1.1.tgz",
|
||||
"integrity": "sha512-WeX8kVS46aobM9a7Xr/kEPcrTyiwJqQv/tbw6nhJ4fH9xNZ+cEcyPoQkwPo570dCOLz3Zo9S2q0E6lJ/EAUOBg==",
|
||||
"optional": true
|
||||
},
|
||||
"@next/swc-win32-x64-msvc": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.1.1.tgz",
|
||||
"integrity": "sha512-mVF0/3/5QAc5EGVnb8ll31nNvf3BWpPY4pBb84tk+BfQglWLqc5AC9q1Ht/YMWiEgs8ALNKEQ3GQnbY0bJF2Gg==",
|
||||
"optional": true
|
||||
},
|
||||
"@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user