primitive-functions 0.2.0-alpha.8 → 0.2.0-alpha.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +174 -28
- package/index.js +30 -0
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -32,8 +32,15 @@ export interface FunctionUser {
|
|
|
32
32
|
* that the fire path does not set.
|
|
33
33
|
*/
|
|
34
34
|
export type FunctionTrigger =
|
|
35
|
-
/**
|
|
36
|
-
|
|
35
|
+
/**
|
|
36
|
+
* An HTTP invocation: the caller is `ctx.user`.
|
|
37
|
+
*
|
|
38
|
+
* `runKey` is the key a `start` was coalesced by (#3562) — what you
|
|
39
|
+
* passed as `runKey` to make the run a singleton — and null when the
|
|
40
|
+
* start named none, or when the call was an `invoke`, which coalesces
|
|
41
|
+
* nothing.
|
|
42
|
+
*/
|
|
43
|
+
| { kind: "http"; runKey: string | null }
|
|
37
44
|
/** A verified webhook delivery to the function's own key. */
|
|
38
45
|
| {
|
|
39
46
|
kind: "webhook";
|
|
@@ -56,8 +63,6 @@ export type FunctionTrigger =
|
|
|
56
63
|
/** Present, and true, only on the diagnostic fire: nothing was scheduled. */
|
|
57
64
|
manual?: true;
|
|
58
65
|
}
|
|
59
|
-
/** A write to a watched database type. */
|
|
60
|
-
| { kind: "database"; databaseId: string; databaseType: string }
|
|
61
66
|
/**
|
|
62
67
|
* A DSL workflow's `workflow.call` step reached this function (#3288).
|
|
63
68
|
*
|
|
@@ -71,19 +76,25 @@ export type FunctionTrigger =
|
|
|
71
76
|
* Another function started this one with `ctx.functions.start` (#3280).
|
|
72
77
|
*
|
|
73
78
|
* `functionKey` names the PARENT, and `runId` its run — null when the
|
|
74
|
-
* parent was a request invocation over HTTP, which writes no run row
|
|
75
|
-
*
|
|
79
|
+
* parent was a request invocation over HTTP, which writes no run row.
|
|
80
|
+
* `runKey` is the key the parent's start named, or null (#3562).
|
|
76
81
|
*/
|
|
77
|
-
| {
|
|
82
|
+
| {
|
|
83
|
+
kind: "function";
|
|
84
|
+
functionKey: string;
|
|
85
|
+
runId: string | null;
|
|
86
|
+
runKey: string | null;
|
|
87
|
+
}
|
|
78
88
|
/**
|
|
79
89
|
* An admin ran this function as the SYSTEM, from outside any trigger
|
|
80
90
|
* (#3448) — `primitive functions invoke --as system`.
|
|
81
91
|
*
|
|
82
92
|
* `ctx.user` is null and the code runs with the app's system authority, as
|
|
83
93
|
* it does for a cron or webhook fire. `userId` names the admin who asked:
|
|
84
|
-
* attribution, never the principal the code runs as.
|
|
94
|
+
* attribution, never the principal the code runs as. `runKey` is the key
|
|
95
|
+
* the admin's start named, or null (#3562).
|
|
85
96
|
*/
|
|
86
|
-
| { kind: "manual"; userId: string };
|
|
97
|
+
| { kind: "manual"; userId: string; runKey: string | null };
|
|
87
98
|
|
|
88
99
|
/** The result shape of an operation that answers in response headers. */
|
|
89
100
|
export interface HeaderResult {
|
|
@@ -717,6 +728,12 @@ export interface FunctionApi {
|
|
|
717
728
|
}): Promise<any>;
|
|
718
729
|
};
|
|
719
730
|
"documents": {
|
|
731
|
+
/** `documents.abortIngest` — POST /documents/{documentId}/ingest/{sessionId}/abort. Abort a bulk-load session before its swap */
|
|
732
|
+
"abortIngest"(args: {
|
|
733
|
+
"documentId": string | number;
|
|
734
|
+
"sessionId": string | number;
|
|
735
|
+
body: unknown;
|
|
736
|
+
}): Promise<any>;
|
|
720
737
|
/** `documents.addTag` — POST /documents/{documentId}/tags. Add a tag to a document */
|
|
721
738
|
"addTag"(args: {
|
|
722
739
|
"documentId": string | number;
|
|
@@ -794,10 +811,21 @@ export interface FunctionApi {
|
|
|
794
811
|
"clearLinkAccess"(args: {
|
|
795
812
|
"documentId": string | number;
|
|
796
813
|
}): Promise<any>;
|
|
814
|
+
/** `documents.commitIngest` — POST /documents/{documentId}/ingest/{sessionId}/commit. Commit a bulk-load session: freeze its manifest and apply it */
|
|
815
|
+
"commitIngest"(args: {
|
|
816
|
+
"documentId": string | number;
|
|
817
|
+
"sessionId": string | number;
|
|
818
|
+
body: unknown;
|
|
819
|
+
}): Promise<any>;
|
|
797
820
|
/** `documents.create` — POST /documents. Create a new document */
|
|
798
821
|
"create"(args: {
|
|
799
822
|
body: unknown;
|
|
800
823
|
}): Promise<any>;
|
|
824
|
+
/** `documents.createIngest` — POST /documents/{documentId}/ingest. Open a bulk-load session on a large document */
|
|
825
|
+
"createIngest"(args: {
|
|
826
|
+
"documentId": string | number;
|
|
827
|
+
body: unknown;
|
|
828
|
+
}): Promise<any>;
|
|
801
829
|
/** `documents.createWithAlias` — POST /documents/create-with-alias. Create a document and bind it to an alias */
|
|
802
830
|
"createWithAlias"(args: {
|
|
803
831
|
body: unknown;
|
|
@@ -855,6 +883,11 @@ export interface FunctionApi {
|
|
|
855
883
|
"getImportChainStatus"(args: {
|
|
856
884
|
"documentId": string | number;
|
|
857
885
|
}): Promise<any>;
|
|
886
|
+
/** `documents.getIngest` — GET /documents/{documentId}/ingest/{sessionId}. One bulk-load session's status */
|
|
887
|
+
"getIngest"(args: {
|
|
888
|
+
"documentId": string | number;
|
|
889
|
+
"sessionId": string | number;
|
|
890
|
+
}): Promise<any>;
|
|
858
891
|
/** `documents.getLinkAccess` — GET /documents/{documentId}/link-access. Get the document's "anyone with the link" access level */
|
|
859
892
|
"getLinkAccess"(args: {
|
|
860
893
|
"documentId": string | number;
|
|
@@ -913,6 +946,12 @@ export interface FunctionApi {
|
|
|
913
946
|
"listGroupPermissions"(args: {
|
|
914
947
|
"documentId": string | number;
|
|
915
948
|
}): Promise<any>;
|
|
949
|
+
/** `documents.listIngests` — GET /documents/{documentId}/ingest. List a large document's bulk-load sessions, newest first */
|
|
950
|
+
"listIngests"(args: {
|
|
951
|
+
"documentId": string | number;
|
|
952
|
+
"limit"?: string | number | boolean;
|
|
953
|
+
"cursor"?: string | number | boolean;
|
|
954
|
+
}): Promise<any>;
|
|
916
955
|
/** `documents.listPendingInvitations` — GET /documents/{documentId}/pending-invitations. List a document's pending (deferred) invitations */
|
|
917
956
|
"listPendingInvitations"(args: {
|
|
918
957
|
"documentId": string | number;
|
|
@@ -1019,6 +1058,12 @@ export interface FunctionApi {
|
|
|
1019
1058
|
"documentId": string | number;
|
|
1020
1059
|
body: unknown;
|
|
1021
1060
|
}): Promise<any>;
|
|
1061
|
+
/** `documents.uploadIngestChunk` — POST /documents/{documentId}/ingest/{sessionId}/chunks. Upload one chunk of a bulk-load session's artifact */
|
|
1062
|
+
"uploadIngestChunk"(args: {
|
|
1063
|
+
"documentId": string | number;
|
|
1064
|
+
"sessionId": string | number;
|
|
1065
|
+
body: FormData | ArrayBuffer | Uint8Array | string;
|
|
1066
|
+
}): Promise<any>;
|
|
1022
1067
|
/** `documents.validateAccess` — POST /documents/{documentId}/validate-access. Resolve the caller's effective access level for a document */
|
|
1023
1068
|
"validateAccess"(args: {
|
|
1024
1069
|
"documentId": string | number;
|
|
@@ -1048,7 +1093,7 @@ export interface FunctionApi {
|
|
|
1048
1093
|
"cursor"?: string | number | boolean;
|
|
1049
1094
|
"runId"?: string | number | boolean;
|
|
1050
1095
|
}): Promise<any>;
|
|
1051
|
-
/** `functions.start` — POST /functions/{functionKey}/start. Start a
|
|
1096
|
+
/** `functions.start` — POST /functions/{functionKey}/start. Start a server function as a task run */
|
|
1052
1097
|
"start"(args: {
|
|
1053
1098
|
"functionKey": string | number;
|
|
1054
1099
|
body?: unknown;
|
|
@@ -1339,8 +1384,8 @@ export type DatabaseModels<K extends string> = K extends keyof DatabaseSchemas
|
|
|
1339
1384
|
* The app's functions, key by key — EMPTY here and filled by the declaration
|
|
1340
1385
|
* `primitive config push` writes into the config tree's `functions/`
|
|
1341
1386
|
* directory (`primitive-function-types.d.ts`): each key's declared input and
|
|
1342
|
-
* output types
|
|
1343
|
-
*
|
|
1387
|
+
* output types, from its `inputSchema` and `outputSchema`. It is what types
|
|
1388
|
+
* `defineFunction("<key>", handler)`.
|
|
1344
1389
|
*/
|
|
1345
1390
|
export interface FunctionSchemas {}
|
|
1346
1391
|
|
|
@@ -1368,20 +1413,6 @@ export type FunctionOutput<K extends string> = K extends keyof FunctionSchemas
|
|
|
1368
1413
|
: any
|
|
1369
1414
|
: any;
|
|
1370
1415
|
|
|
1371
|
-
/**
|
|
1372
|
-
* A declared function's mode, fixed at generation time.
|
|
1373
|
-
*
|
|
1374
|
-
* `"any"` — the default when the authored file names no mode (#3454) — takes
|
|
1375
|
-
* EITHER runner and the caller picks at call time; `"request"` and `"task"`
|
|
1376
|
-
* lock it to one. An UNDECLARED key is the whole union, because nothing has
|
|
1377
|
-
* said which of the three it is.
|
|
1378
|
-
*/
|
|
1379
|
-
export type FunctionMode<K extends string> = K extends keyof FunctionSchemas
|
|
1380
|
-
? FunctionSchemas[K] extends { mode: infer M }
|
|
1381
|
-
? M
|
|
1382
|
-
: "request" | "task" | "any"
|
|
1383
|
-
: "request" | "task" | "any";
|
|
1384
|
-
|
|
1385
1416
|
/**
|
|
1386
1417
|
* The model names one database type addresses — its own, or any name at all
|
|
1387
1418
|
* for a type that declares no schema (the DO is schemaless, so a grant on such
|
|
@@ -1551,6 +1582,26 @@ export interface DocumentQueryOptions {
|
|
|
1551
1582
|
* One document model, bound to its document and its model name — a thin
|
|
1552
1583
|
* binding over `ctx.api.documents.records.*` with the route's own shapes.
|
|
1553
1584
|
*/
|
|
1585
|
+
/**
|
|
1586
|
+
* One op of a document `batch` — the `documents.records.bulk` blob's shape,
|
|
1587
|
+
* typed to this handle's model (#3455).
|
|
1588
|
+
*
|
|
1589
|
+
* `model` is NOT a member: the handle already names it and assigns it last, so
|
|
1590
|
+
* a multi-model blob stays on the raw `ctx.api.documents.records.bulk`
|
|
1591
|
+
* operation rather than becoming a second way to say the same thing.
|
|
1592
|
+
*/
|
|
1593
|
+
export type DocumentBatchOp<TRow> =
|
|
1594
|
+
| { action: "create" | "patch"; id: string; data: Partial<TRow>; precondition?: Record<string, unknown> }
|
|
1595
|
+
| { action: "delete"; id: string; precondition?: Record<string, unknown> };
|
|
1596
|
+
|
|
1597
|
+
/** What `documents.records.bulk` answers: the blob's aggregate effect. */
|
|
1598
|
+
export interface DocumentBulkResult {
|
|
1599
|
+
applied: number;
|
|
1600
|
+
added: Array<{ model: string; id: string }>;
|
|
1601
|
+
updated: Array<{ model: string; id: string }>;
|
|
1602
|
+
deleted: number;
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1554
1605
|
export interface DocumentModelHandle<TRow> {
|
|
1555
1606
|
query(options?: DocumentQueryOptions): Promise<{ items: TRow[]; hasMore: boolean; nextCursor?: string }>;
|
|
1556
1607
|
count(options?: { filter?: Record<string, unknown> | string }): Promise<{ count: number }>;
|
|
@@ -1558,6 +1609,15 @@ export interface DocumentModelHandle<TRow> {
|
|
|
1558
1609
|
save(body: { id: string; data: Partial<TRow>; options?: Record<string, unknown> }): Promise<{ record: TRow }>;
|
|
1559
1610
|
patch(recordId: string, body: { data: Partial<TRow>; options?: Record<string, unknown> }): Promise<{ record: TRow }>;
|
|
1560
1611
|
delete(recordId: string): Promise<{ deleted: boolean }>;
|
|
1612
|
+
/**
|
|
1613
|
+
* Apply an ordered blob of this model's ops in ONE transaction — all of it
|
|
1614
|
+
* commits or none of it does, and connected clients see one update.
|
|
1615
|
+
*
|
|
1616
|
+
* One model's ops, by construction: every op's `model` is this handle's.
|
|
1617
|
+
* A blob that spans models is the raw `ctx.api.documents.records.bulk`
|
|
1618
|
+
* operation's job.
|
|
1619
|
+
*/
|
|
1620
|
+
batch(ops: Array<DocumentBatchOp<TRow>>): Promise<DocumentBulkResult>;
|
|
1561
1621
|
}
|
|
1562
1622
|
|
|
1563
1623
|
/** A document, addressed once; its models are typed from `DocumentSchemas`. */
|
|
@@ -1785,9 +1845,45 @@ export interface FunctionStartResult {
|
|
|
1785
1845
|
}
|
|
1786
1846
|
|
|
1787
1847
|
export interface FunctionContext {
|
|
1788
|
-
/** The HTTP caller, or null for a webhook
|
|
1848
|
+
/** The HTTP caller, or null for a webhook or cron fire. */
|
|
1789
1849
|
user: FunctionUser | null;
|
|
1790
1850
|
trigger: FunctionTrigger;
|
|
1851
|
+
/**
|
|
1852
|
+
* Which RUNTIME is hosting this code — #3482.
|
|
1853
|
+
*
|
|
1854
|
+
* Beside `trigger`, which says which DOOR fired, and they are different
|
|
1855
|
+
* questions: an HTTP call is whichever runtime the caller chose
|
|
1856
|
+
* (`invoke` or `start`), a cron fire is always a task and a webhook
|
|
1857
|
+
* delivery is always a request.
|
|
1858
|
+
*
|
|
1859
|
+
* To REFUSE a runtime rather than branch on it, call
|
|
1860
|
+
* `assertRuntime("task")` — at module scope to refuse it outright, or in
|
|
1861
|
+
* the handler to refuse one call.
|
|
1862
|
+
*/
|
|
1863
|
+
runtime: "request" | "task";
|
|
1864
|
+
/**
|
|
1865
|
+
* The RUN this invocation belongs to, or null — #3562.
|
|
1866
|
+
*
|
|
1867
|
+
* Set under the task runtime (every slice of the run, the first and every
|
|
1868
|
+
* resume) and for a webhook-fired request run, which writes a row. Null for
|
|
1869
|
+
* an HTTP `invoke`, which writes no run row at all.
|
|
1870
|
+
*
|
|
1871
|
+
* It is the deterministic OWNER a task run presents to re-take its own
|
|
1872
|
+
* lease: `ctx.api.locks.tryAcquire({ body: { key, ttlMs, owner: ctx.runId } })`
|
|
1873
|
+
* succeeds for the run that already holds the key, with a fresh handle.
|
|
1874
|
+
*/
|
|
1875
|
+
runId: string | null;
|
|
1876
|
+
/**
|
|
1877
|
+
* The SLICE of the run this code is running in, or null — #3562.
|
|
1878
|
+
*
|
|
1879
|
+
* The same identifier `primitive functions runs` and the run-status
|
|
1880
|
+
* route's `slice.sliceId` report. A task run is a sequence of slices: it
|
|
1881
|
+
* changes when the run hibernates and wakes, which is how a handler can tell
|
|
1882
|
+
* a resume from a first pass.
|
|
1883
|
+
*
|
|
1884
|
+
* Null under the request runtime: a request invocation is not a slice.
|
|
1885
|
+
*/
|
|
1886
|
+
sliceId: string | null;
|
|
1791
1887
|
api: FunctionApi;
|
|
1792
1888
|
/**
|
|
1793
1889
|
* A typed handle over one database. The second argument is the database TYPE
|
|
@@ -1949,7 +2045,7 @@ export interface FunctionContext {
|
|
|
1949
2045
|
* clock: `do` executes the body inline (there is no engine to memoize into,
|
|
1950
2046
|
* and nothing is replayed); `sleep` and `sleepUntil` REALLY wait when the
|
|
1951
2047
|
* remaining request budget covers the duration, and otherwise fail the
|
|
1952
|
-
* invocation with `errorCode: "
|
|
2048
|
+
* invocation with `errorCode: "FUNCTION_RUNTIME_REFUSED"` saying to start the
|
|
1953
2049
|
* function as a task; `waitForEvent` fails the same way, because nothing can
|
|
1954
2050
|
* deliver an event to an invocation that has to return now. The thrown error's
|
|
1955
2051
|
* `name` is `STEP_NOT_AVAILABLE` in every case, so a body that catches it
|
|
@@ -1972,6 +2068,48 @@ export interface FunctionStep {
|
|
|
1972
2068
|
|
|
1973
2069
|
export declare const SDK_STUB_VERSION: string;
|
|
1974
2070
|
|
|
2071
|
+
/**
|
|
2072
|
+
* Thrown by `assertRuntime` when this function is running under the other
|
|
2073
|
+
* runtime — #3482.
|
|
2074
|
+
*
|
|
2075
|
+
* The platform settles it as `status: "failed"` with
|
|
2076
|
+
* `errorCode: "FUNCTION_RUNTIME_REFUSED"`, on a request invocation's
|
|
2077
|
+
* envelope and on a task run's row and record alike.
|
|
2078
|
+
*/
|
|
2079
|
+
export declare class FunctionRuntimeError extends Error {
|
|
2080
|
+
name: "FUNCTION_RUNTIME_REFUSED";
|
|
2081
|
+
/** The runtime this invocation is actually running under. */
|
|
2082
|
+
runtime: "request" | "task";
|
|
2083
|
+
/** The runtime the function asked for. */
|
|
2084
|
+
required: "request" | "task";
|
|
2085
|
+
}
|
|
2086
|
+
|
|
2087
|
+
/**
|
|
2088
|
+
* Refuse the runtime this function was not written for — #3482.
|
|
2089
|
+
*
|
|
2090
|
+
* A function is a function and the caller picks the runtime at each call, so
|
|
2091
|
+
* nothing in config says which one a function may run under. This is the lock,
|
|
2092
|
+
* and it lives in the one place that can always be right about the code:
|
|
2093
|
+
*
|
|
2094
|
+
* ```ts
|
|
2095
|
+
* import { assertRuntime } from "primitive-functions";
|
|
2096
|
+
*
|
|
2097
|
+
* // At module scope: this function is never runnable inside a request.
|
|
2098
|
+
* assertRuntime("task");
|
|
2099
|
+
*
|
|
2100
|
+
* export default async function (input, ctx, step) {
|
|
2101
|
+
* await step.sleep("cool-off", "1 hour");
|
|
2102
|
+
* return { ok: true };
|
|
2103
|
+
* }
|
|
2104
|
+
* ```
|
|
2105
|
+
*
|
|
2106
|
+
* Returns when the runtimes match; otherwise throws
|
|
2107
|
+
* {@link FunctionRuntimeError}, which the platform settles as
|
|
2108
|
+
* `status: "failed"` with `errorCode: "FUNCTION_RUNTIME_REFUSED"` and a
|
|
2109
|
+
* message naming both runtimes and the verb that takes the one required.
|
|
2110
|
+
*/
|
|
2111
|
+
export declare function assertRuntime(required: "request" | "task"): void;
|
|
2112
|
+
|
|
1975
2113
|
/**
|
|
1976
2114
|
* The handler a function exports, typed for one declared key.
|
|
1977
2115
|
*
|
|
@@ -2204,6 +2342,12 @@ export declare const stepPolicy: {
|
|
|
2204
2342
|
database: StepPolicy;
|
|
2205
2343
|
};
|
|
2206
2344
|
|
|
2345
|
+
// Every member the three runtime copies put on their own default export — the
|
|
2346
|
+
// platform's `sdk-core.ts`, the published stub and the CLI's collect stub —
|
|
2347
|
+
// and nothing else. A helper the module hands a default import but does not
|
|
2348
|
+
// declare here is one an author cannot call without the compiler refusing it
|
|
2349
|
+
// (#3482 CR3482-002); `tests/api/spec/function-profile.test.ts` holds the four
|
|
2350
|
+
// lists equal and compiles a default import against them.
|
|
2207
2351
|
declare const _default: {
|
|
2208
2352
|
SDK_STUB_VERSION: string;
|
|
2209
2353
|
defineFunction: typeof defineFunction;
|
|
@@ -2211,5 +2355,7 @@ declare const _default: {
|
|
|
2211
2355
|
defineMutation: typeof defineMutation;
|
|
2212
2356
|
pMap: typeof pMap;
|
|
2213
2357
|
ulid: typeof ulid;
|
|
2358
|
+
assertRuntime: typeof assertRuntime;
|
|
2359
|
+
FunctionRuntimeError: typeof FunctionRuntimeError;
|
|
2214
2360
|
};
|
|
2215
2361
|
export default _default;
|
package/index.js
CHANGED
|
@@ -82,6 +82,34 @@ export const stepPolicy = {
|
|
|
82
82
|
database: null,
|
|
83
83
|
};
|
|
84
84
|
|
|
85
|
+
/**
|
|
86
|
+
* The runtime refusal's error class — #3482.
|
|
87
|
+
*
|
|
88
|
+
* Carried rather than thrown from: a function narrows a `catch` with
|
|
89
|
+
* `instanceof FunctionRuntimeError`, and a class that threw on construction
|
|
90
|
+
* would break a build that only type-checks. The platform copy is the one that
|
|
91
|
+
* is ever really thrown.
|
|
92
|
+
*/
|
|
93
|
+
export class FunctionRuntimeError extends Error {
|
|
94
|
+
constructor(message, runtime, required) {
|
|
95
|
+
super(message);
|
|
96
|
+
this.name = "FUNCTION_RUNTIME_REFUSED";
|
|
97
|
+
this.runtime = runtime;
|
|
98
|
+
this.required = required;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Refuse the runtime this function was not written for — #3482.
|
|
104
|
+
*
|
|
105
|
+
* The platform copy compares the required runtime against the one the isolate
|
|
106
|
+
* declared. This one refuses, loudly, like every other function here: an
|
|
107
|
+
* assertion answered outside a sandbox would be answering about nothing.
|
|
108
|
+
*/
|
|
109
|
+
export function assertRuntime() {
|
|
110
|
+
throw new Error(NOT_PROVIDED);
|
|
111
|
+
}
|
|
112
|
+
|
|
85
113
|
export default {
|
|
86
114
|
SDK_STUB_VERSION,
|
|
87
115
|
defineFunction,
|
|
@@ -89,4 +117,6 @@ export default {
|
|
|
89
117
|
defineMutation,
|
|
90
118
|
pMap,
|
|
91
119
|
ulid,
|
|
120
|
+
assertRuntime,
|
|
121
|
+
FunctionRuntimeError,
|
|
92
122
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "primitive-functions",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.9",
|
|
4
4
|
"description": "The module a Primitive server function imports. Supplied by the platform at invoke time; reserved here so the name is ours before the runtime lands.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"author": "Primitive LLC",
|