Skip to content

Commit

Permalink
Implement a basic fetch seed_type.
Browse files Browse the repository at this point in the history
Part of #45.
  • Loading branch information
jkomoros committed Jul 22, 2023
1 parent 2bffd90 commit 76525e0
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 5 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,18 @@ Parameters:
- `reference` - The packed reference to the seed to execute. You can retrieve one with `reference`
- `allow_remote` - (optional) - if set to true, then remote references will not fail. This is a dangerous property!
#### fetch
Fetches a remote resource and returns the text of the resoponse. You can extract the JSON of the response using the `extract` seed_type with the template `{{data|json}}`.
Parameters:
- `resource` - The URL of the resource to fetch
- `method` - (optional) the HTTP method (GET or PUT). Defaults to GET
- `body` - (optional) the body to provide in the resource if it is not a GET method.
Environment:
- `mock` - If true, will return a string representation of the request that would have been sent.
#### property
Selects a named property from an object
Expand Down
92 changes: 89 additions & 3 deletions seed-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1785,6 +1785,92 @@
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"id": {
"$ref": "#/definitions/seedData/anyOf/0/properties/id"
},
"description": {
"$ref": "#/definitions/seedData/anyOf/0/properties/description"
},
"comment": {
"$ref": "#/definitions/seedData/anyOf/0/properties/comment"
},
"private": {
"$ref": "#/definitions/seedData/anyOf/0/properties/private"
},
"type": {
"type": "string",
"const": "fetch"
},
"resource": {
"anyOf": [
{
"$ref": "#/definitions/seedData"
},
{
"$ref": "#/definitions/seedData/anyOf/0/properties/prompt/anyOf/1"
},
{
"type": "string",
"description": "The URL of the resource to fetch"
}
]
},
"method": {
"anyOf": [
{
"$ref": "#/definitions/seedData"
},
{
"$ref": "#/definitions/seedData/anyOf/0/properties/prompt/anyOf/1"
},
{
"anyOf": [
{
"not": {}
},
{
"type": "string",
"enum": [
"GET",
"POST"
]
}
],
"description": "The method (default GET)"
}
]
},
"body": {
"anyOf": [
{
"$ref": "#/definitions/seedData"
},
{
"$ref": "#/definitions/seedData/anyOf/0/properties/prompt/anyOf/1"
},
{
"anyOf": [
{
"not": {}
},
{
"type": "string"
}
],
"description": "The body to pass"
}
]
}
},
"required": [
"type",
"resource"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
Expand Down Expand Up @@ -1965,7 +2051,7 @@
"items": {
"anyOf": [
{
"$ref": "#/definitions/seedData/anyOf/26/properties/properties/additionalProperties/anyOf/0"
"$ref": "#/definitions/seedData/anyOf/27/properties/properties/additionalProperties/anyOf/0"
},
{
"$ref": "#/definitions/seedData/anyOf/0/properties/prompt/anyOf/1"
Expand All @@ -1979,7 +2065,7 @@
"return": {
"anyOf": [
{
"$ref": "#/definitions/seedData/anyOf/26/properties/properties/additionalProperties/anyOf/0"
"$ref": "#/definitions/seedData/anyOf/27/properties/properties/additionalProperties/anyOf/0"
},
{
"$ref": "#/definitions/seedData/anyOf/0/properties/prompt/anyOf/1"
Expand Down Expand Up @@ -2546,7 +2632,7 @@
{
"anyOf": [
{
"$ref": "#/definitions/seedData/anyOf/32/properties/name/anyOf/2/anyOf/0"
"$ref": "#/definitions/seedData/anyOf/33/properties/name/anyOf/2/anyOf/0"
},
{
"$ref": "#/definitions/seedData/anyOf/2/properties/memory/anyOf/2/anyOf/1"
Expand Down
35 changes: 33 additions & 2 deletions src/grow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,13 @@ import {
SeedDataRandomSeed,
roundType,
SeedDataSplit,
SeedDataJoin
SeedDataJoin,
SeedDataFetch,
fetchMethod
} from './types.js';

import {
assertUnreachable, getObjectProperty
assertUnreachable, getObjectProperty, mockedResult
} from './util.js';

import {
Expand Down Expand Up @@ -418,6 +420,32 @@ const growDynamic = async (seed : Seed<SeedDataDynamic>, env : Environment) : Pr
return await growSubSeed(seed,env,unpackedRef);
};

const growFetch = async (seed : Seed<SeedDataFetch>, env : Environment) : Promise<string> => {
const data = seed.data;
const resource = extractString(await getProperty(seed, env, data.resource, ''));
if (!resource) throw new Error('no resource passed');
const rawMethod = extractString(await getProperty(seed, env, data.method, 'GET'));
const method = fetchMethod.parse(rawMethod.toUpperCase().trim());
let body = null;
if (method != 'GET') body = extractString(await getProperty(seed, env, data.body, ''));

if (env.getKnownProtectedKey('mock')) {
const data = {
resource,
method,
body
};
return mockedResult(JSON.stringify(data, null, '\t'));
}

const result = await fetch(resource, {
method,
body
});
if (!result.ok) throw new Error(`Result status was not ok: ${result.status}: ${result.statusText}`);
return result.text();
};

const growProperty = async (seed : Seed<SeedDataProperty>, env : Environment) : Promise<Value> => {
const data = seed.data;
const obj = await getProperty(seed, env, data.object);
Expand Down Expand Up @@ -701,6 +729,9 @@ export const grow = async (seed : Seed, env : Environment) : Promise<Value> => {
case 'dynamic':
result = await growDynamic(seed as Seed<SeedDataDynamic>, env);
break;
case 'fetch':
result = await growFetch(seed as Seed<SeedDataFetch>, env);
break;
case 'property':
result = await growProperty(seed as Seed<SeedDataProperty>, env);
break;
Expand Down
23 changes: 23 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,27 @@ const seedDataDynamic = makeSeedData(seedDataConfigDynamic);

export type SeedDataDynamic = z.infer<typeof seedDataDynamic>;

export const fetchMethod = z.union([
z.literal('GET'),
z.literal('POST')
]);

export type FetchMethod = z.infer<typeof fetchMethod>;

const seedDataConfigFetch = {
type: z.literal('fetch'),
properties: {
resource: z.string().describe('The URL of the resource to fetch'),
method: fetchMethod.optional().describe('The method (default GET)'),
body: z.string().optional().describe('The body to pass')
}
};

const nestedSeedDataFetch = makeNestedSeedData(seedDataConfigFetch);
const seedDataFetch = makeSeedData(seedDataConfigFetch);

export type SeedDataFetch = z.infer<typeof seedDataFetch>;

const seedDataConfigKeys = {
type: z.literal('keys'),
properties: {
Expand Down Expand Up @@ -961,6 +982,7 @@ export const expandedSeedData = z.discriminatedUnion('type', [
seedDataInput,
seedDataReference,
seedDataDynamic,
seedDataFetch,
seedDataKeys,
seedDataProperty,
seedDataObject,
Expand Down Expand Up @@ -1006,6 +1028,7 @@ export const seedData = z.discriminatedUnion('type', [
nestedSeedDataInput,
nestedSeedDataReference,
nestedSeedDataDynamic,
nestedSeedDataFetch,
nestedSeedDataKeys,
nestedSeedDataProperty,
nestedSeedDataObject,
Expand Down
5 changes: 5 additions & 0 deletions test/base/a_test.json
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,11 @@
]
},
"property": "a.1"
},
"fetch-test": {
"type": "fetch",
"resource": "https://raw.githubusercontent.com/jkomoros/prompt-garden/main/seeds/example-basic.json",
"method": "POST"
}
}
}
12 changes: 12 additions & 0 deletions test/base/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -927,6 +927,18 @@ Suffix`;
assert.deepStrictEqual(actual, golden);
});

it('fetch test', async () => {
const garden = loadTestGarden();
const seed = await garden.seed('fetch-test');
const actual = await seed.grow();
const golden = `Mocked result: {
"resource": "https://raw.githubusercontent.com/jkomoros/prompt-garden/main/seeds/example-basic.json",
"method": "POST",
"body": ""
}`;
assert.deepStrictEqual(actual, golden);
});

});

describe('expandSeedPacket tests', () => {
Expand Down

0 comments on commit 76525e0

Please sign in to comment.