@picked/client 0.0.71-next.1 → 0.0.71-next.3
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/dist/.tsbuildinfo +1 -1
- package/dist/{api-CH2FNa6S.cjs → api-CnjBi6JG.cjs} +1 -1
- package/dist/{api-CgqRvuKL.js → api-vBVGLtvU.js} +1 -1
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/plugins/dynamic-experiences/index.js +1 -1
- package/dist/cjs/server/index.js +1 -1
- package/dist/docs/explanation/conditions-and-the-logic-engine.md +94 -0
- package/dist/docs/explanation/feature-flag-allocation.md +176 -0
- package/dist/docs/explanation/how-picked-works.md +102 -0
- package/dist/docs/explanation/how-pickedql-works.md +76 -0
- package/dist/docs/explanation/pages-and-flows.md +64 -0
- package/dist/docs/explanation/the-content-model.md +77 -0
- package/dist/docs/explanation/the-two-apis.md +68 -0
- package/dist/docs/explanation/why-server-side-rendering.md +76 -0
- package/dist/docs/explanation/workspaces-and-versions.md +71 -0
- package/dist/docs/how-to/add-a-step-field-or-action.md +43 -0
- package/dist/docs/{pickedql/examples.md → how-to/analytics/index.md} +19 -6
- package/dist/docs/how-to/archive-or-delete-a-workspace.md +46 -0
- package/dist/docs/how-to/authenticate-with-a-magic-link.md +40 -0
- package/dist/docs/how-to/authenticate-with-a-password.md +51 -0
- package/dist/docs/how-to/authenticate-with-an-api-key.md +51 -0
- package/dist/docs/how-to/authenticate-with-oauth.md +40 -0
- package/dist/docs/{flow-builder/building-flows.md → how-to/build-a-flow.md} +13 -9
- package/dist/docs/how-to/connect-the-mcp-server.md +38 -0
- package/dist/docs/how-to/create-a-project.md +29 -0
- package/dist/docs/how-to/create-an-experience.md +42 -0
- package/dist/docs/how-to/create-and-revoke-an-api-key.md +37 -0
- package/dist/docs/how-to/debug-with-the-chrome-extension.md +57 -0
- package/dist/docs/how-to/define-a-page-layout.md +39 -0
- package/dist/docs/how-to/fill-and-publish-a-page.md +50 -0
- package/dist/docs/{gtm-template.md → how-to/install-the-gtm-template.md} +9 -3
- package/dist/docs/how-to/install-the-sdk.md +68 -0
- package/dist/docs/how-to/install-the-vite-plugin.md +56 -0
- package/dist/docs/how-to/invite-and-remove-members.md +34 -0
- package/dist/docs/how-to/preview-a-workspace.md +28 -0
- package/dist/docs/how-to/publish-a-workspace.md +30 -0
- package/dist/docs/how-to/read-a-feature-flag.md +101 -0
- package/dist/docs/how-to/register-a-component.md +55 -0
- package/dist/docs/how-to/register-an-action-handler.md +67 -0
- package/dist/docs/how-to/render-a-step-form.md +132 -0
- package/dist/docs/how-to/render-an-unpublished-preview.md +41 -0
- package/dist/docs/how-to/reuse-a-section.md +37 -0
- package/dist/docs/how-to/reuse-a-step-field-or-action.md +28 -0
- package/dist/docs/how-to/roll-back-a-published-version.md +26 -0
- package/dist/docs/how-to/run-an-ab-test.md +49 -0
- package/dist/docs/how-to/run-code-on-a-form-submission.md +125 -0
- package/dist/docs/how-to/server-render-a-page.md +81 -0
- package/dist/docs/how-to/set-a-content-security-policy.md +32 -0
- package/dist/docs/how-to/set-up-mfa.md +69 -0
- package/dist/docs/how-to/upload-and-use-an-asset.mdx +73 -0
- package/dist/docs/how-to/validate-a-field.md +52 -0
- package/dist/docs/how-to/write-a-condition.md +45 -0
- package/dist/docs/how-to/write-a-predicate.md +60 -0
- package/dist/docs/index.md +41 -70
- package/dist/docs/reference/dashboard/actions.mdx +53 -0
- package/dist/docs/{api-keys.mdx → reference/dashboard/api-keys.mdx} +7 -15
- package/dist/docs/reference/dashboard/conditions.mdx +42 -0
- package/dist/docs/reference/dashboard/content/asset-library.mdx +63 -0
- package/dist/docs/{content → reference/dashboard/content}/content-entries.mdx +11 -3
- package/dist/docs/{content → reference/dashboard/content}/layouts.mdx +11 -35
- package/dist/docs/reference/dashboard/content/pages.mdx +35 -0
- package/dist/docs/reference/dashboard/content/sections.mdx +28 -0
- package/dist/docs/{experiences.mdx → reference/dashboard/experiences.mdx} +9 -16
- package/dist/docs/{features.mdx → reference/dashboard/features.mdx} +26 -41
- package/dist/docs/{fields.mdx → reference/dashboard/fields.mdx} +26 -20
- package/dist/docs/{flow-builder/overview.mdx → reference/dashboard/flow-builder/canvas.mdx} +8 -13
- package/dist/docs/{flow-builder → reference/dashboard/flow-builder}/condition-builder.md +5 -13
- package/dist/docs/{flow-builder → reference/dashboard/flow-builder}/keyboard-shortcuts.md +7 -1
- package/dist/docs/{flow-builder → reference/dashboard/flow-builder}/nodes.md +10 -3
- package/dist/docs/reference/dashboard/projects.mdx +44 -0
- package/dist/docs/reference/dashboard/reports.mdx +43 -0
- package/dist/docs/reference/dashboard/steps.mdx +37 -0
- package/dist/docs/{team-management.md → reference/dashboard/team-management.md} +5 -22
- package/dist/docs/{workspace-versioning.mdx → reference/dashboard/workspace-versioning.mdx} +6 -10
- package/dist/docs/reference/dashboard/workspaces.mdx +76 -0
- package/dist/docs/{delivery-api → reference/delivery-api}/experience-content.md +11 -4
- package/dist/docs/reference/delivery-api/index.md +45 -0
- package/dist/docs/{delivery-api → reference/delivery-api}/preview-caching-crawling.md +12 -5
- package/dist/docs/{delivery-api → reference/delivery-api}/project-config.md +11 -4
- package/dist/docs/reference/glossary.md +173 -0
- package/dist/docs/reference/management-api/authentication.md +74 -0
- package/dist/docs/{api → reference/management-api}/authorization-and-scopes.md +10 -3
- package/dist/docs/{api → reference/management-api}/error-handling.md +9 -3
- package/dist/docs/{api → reference/management-api}/pagination.md +6 -0
- package/dist/docs/{pickedql → reference/pickedql}/data-sources.md +16 -9
- package/dist/docs/{pickedql → reference/pickedql}/dimensions.md +7 -0
- package/dist/docs/{pickedql → reference/pickedql}/filtering.md +7 -0
- package/dist/docs/reference/pickedql/index.md +18 -0
- package/dist/docs/{pickedql → reference/pickedql}/schema.md +13 -6
- package/dist/docs/{pickedql → reference/pickedql}/virtual-functions.md +7 -0
- package/dist/docs/reference/sdk/actions.md +30 -0
- package/dist/docs/{sdk → reference/sdk}/conditions.md +8 -1
- package/dist/docs/reference/sdk/content-security-policy.md +21 -0
- package/dist/docs/reference/sdk/experiences.md +51 -0
- package/dist/docs/{sdk → reference/sdk}/features.md +30 -117
- package/dist/docs/{sdk → reference/sdk}/fields.md +10 -88
- package/dist/docs/reference/sdk/index.md +68 -0
- package/dist/docs/{sdk → reference/sdk}/plugins/create-experience.md +10 -22
- package/dist/docs/reference/sdk/plugins/dynamic-experiences.md +26 -0
- package/dist/docs/reference/sdk/plugins/index.md +29 -0
- package/dist/docs/{sdk → reference/sdk}/plugins/window-object.md +6 -0
- package/dist/docs/reference/sdk/predicates.md +43 -0
- package/dist/docs/reference/sdk/ssr/index.md +33 -0
- package/dist/docs/{sdk → reference/sdk}/ssr/rendering-and-hydration.md +4 -63
- package/dist/docs/{sdk → reference/sdk}/ssr/serialize.md +6 -33
- package/dist/docs/{sdk → reference/sdk}/ssr/slots-and-placements.md +7 -1
- package/dist/docs/reference/sdk/steps.md +87 -0
- package/dist/docs/reference/tools/chrome-extension.md +16 -0
- package/dist/docs/{image-optimisation-service.md → reference/tools/image-optimisation-service.md} +8 -0
- package/dist/docs/{mcp.md → reference/tools/mcp.md} +5 -45
- package/dist/docs/{vite-plugin.md → reference/tools/vite-plugin.md} +8 -38
- package/dist/docs/{api/index.md → tutorials/first-api-call.md} +27 -15
- package/dist/docs/tutorials/first-experience-in-the-dashboard.mdx +143 -0
- package/dist/docs/tutorials/first-experience.mdx +255 -0
- package/dist/docs/tutorials/first-server-rendered-page.mdx +186 -0
- package/dist/esm/index.js +468 -426
- package/dist/esm/plugins/dynamic-experiences/index.js +2 -2
- package/dist/esm/server/index.js +1 -1
- package/dist/{plugin-DCW-tnjO.cjs → plugin-CSmD1gPl.cjs} +1 -1
- package/dist/{plugin-D2UqFikQ.js → plugin-GOTtoDlC.js} +1 -1
- package/dist/types/entities/feature/feature.d.ts +25 -2
- package/dist/types/entities/feature/feature.d.ts.map +1 -1
- package/dist/types/picked.d.ts +2 -1
- package/dist/types/picked.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/docs/actions.mdx +0 -98
- package/dist/docs/api/authentication.md +0 -403
- package/dist/docs/chrome-extension.md +0 -68
- package/dist/docs/conditions.mdx +0 -72
- package/dist/docs/content/asset-library.mdx +0 -124
- package/dist/docs/content/pages.mdx +0 -82
- package/dist/docs/content/sections.mdx +0 -44
- package/dist/docs/delivery-api/index.md +0 -53
- package/dist/docs/guides/build-a-personalized-page.mdx +0 -161
- package/dist/docs/pickedql/index.md +0 -54
- package/dist/docs/projects.mdx +0 -44
- package/dist/docs/reports.mdx +0 -20
- package/dist/docs/sdk/actions.md +0 -82
- package/dist/docs/sdk/content-security-policy.md +0 -33
- package/dist/docs/sdk/experiences.md +0 -64
- package/dist/docs/sdk/feature-allocation.md +0 -161
- package/dist/docs/sdk/index.md +0 -98
- package/dist/docs/sdk/plugins/dynamic-experiences.md +0 -84
- package/dist/docs/sdk/plugins/index.md +0 -9
- package/dist/docs/sdk/predicates.md +0 -128
- package/dist/docs/sdk/ssr/index.md +0 -79
- package/dist/docs/sdk/steps.md +0 -479
- package/dist/docs/steps.mdx +0 -53
- package/dist/docs/workspaces.mdx +0 -133
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { i as e } from "../../../api-
|
|
2
|
-
import { n as t, r as n, t as r } from "../../../plugin-
|
|
1
|
+
import { i as e } from "../../../api-vBVGLtvU.js";
|
|
2
|
+
import { n as t, r as n, t as r } from "../../../plugin-GOTtoDlC.js";
|
|
3
3
|
export { e as createClientHeaders, r as dynamicExperiencesPlugin, t as fetchExperienceContent, n as fetchProject };
|
package/dist/esm/server/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as e, c as t, i as n, o as r, s as i, t as a, u as o } from "../../experience-instance-DGk11d8a.js";
|
|
2
|
-
import { i as s, n as c } from "../../plugin-
|
|
2
|
+
import { i as s, n as c } from "../../plugin-GOTtoDlC.js";
|
|
3
3
|
import { attach as l, createEffect as u, createEvent as d, createStore as f, sample as p } from "effector";
|
|
4
4
|
//#region src/server/serialize.ts
|
|
5
5
|
var m = 1e4;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
require("./logger-CSTvAyyB.cjs");const e=require("./api-
|
|
1
|
+
require("./logger-CSTvAyyB.cjs");const e=require("./api-CnjBi6JG.cjs");let t=require("effector");function n(e){let t=2166136261;for(let n of e)t^=n.codePointAt(0)??0,t=Math.imul(t,16777619);return t>>>0}function r(e){let t=e;return t^=t>>>16,t=Math.imul(t,2246822507),t^=t>>>13,t=Math.imul(t,3266489909),t^=t>>>16,t>>>0}function i(e,t){return r(n(`${e}:${t}`))%100}function a(e,t){return t<=0?!1:t>=100||e<t}function o(e){return typeof e==`object`&&!!e&&`features`in e&&Array.isArray(e.features)}function s(e,t){if(Array.isArray(t.conditions))for(let n of t.conditions)e.registerCondition(n)}function c(e,t){e.registerExperience({id:t.id,key:t.key,name:t.name,targets:t.targets,nodes:t.nodes,edges:t.edges,condition:t.condition,initializeOpen:t.initializeOpen,componentName:t.componentName})}function l(e,t){if(Array.isArray(t.fields))for(let n of t.fields)e.registerField(n)}function u(e,t){if(!Array.isArray(t.steps))return;let n=new Map(t.fields.map(e=>[e.id,e.key]));for(let r of t.steps){let t=[];for(let e of r.fieldIds??[]){let i=n.get(e);if(i===void 0){`${r.key}${e}`;continue}t.push(i)}let i=r.layoutContentId?e.contents.getById(r.layoutContentId):null;e.registerStep({id:r.id,key:r.key,name:r.name,fieldKeys:t,layoutName:r.layoutName,...r.layoutContentId!==void 0&&{layoutContentId:r.layoutContentId,layoutContentStore:i}})}}function d(e,t){if(Array.isArray(t.experiences))for(let n of t.experiences)c(e,n)}function f(e,t,n){h(e,t,n.isPreview,n.sessionId),s(e,t),l(e,t),u(e,t),d(e,t)}function p(e){let t=e.searchParams[`preview-token`];if(t&&t.length>0)return t[0]}function m(e){let t=new Set,n=e.searchParams.feature;if(!n)return t;for(let e of n){let n=e.indexOf(`:`);n>0&&t.add(e.substring(0,n))}return t}function h(e,t,n,r){let i=m(e);for(let a of t.features)i.has(a.id)||g(e,a,n,r)}function g(e,t,n,r){let o=i(r,t.id);e.registerFeature(t.id,{key:`v${t.version}`,name:t.name,enabled:t.enabled,weight:t.weight,storage:n?`session`:`local`,decide:()=>a(o,t.weight)})}function _(e){try{let t=new URL(e).hostname;return t===`localhost`||t===`127.0.0.1`||t===`::1`}catch{return!1}}function v(e){if(typeof e!=`object`||!e||!(`cause`in e))return!1;let{cause:t}=e;return typeof t!=`object`||!t||!(`code`in t)?!1:t.code===`ECONNREFUSED`}async function y(t,n,r){let i=r?.previewToken?`projects/${n}?preview_token=${encodeURIComponent(r.previewToken)}`:`projects/${n}`,a;try{a=await e.t(t,i,r?.headers)}catch(e){return _(t)&&v(e),null}if(!a.ok)return`${a.status.toString()}`,null;let s;try{s=await a.json()}catch{return null}return o(s)?s:null}function b(e){return typeof e!=`object`||!e||!(`experienceId`in e)||!(`content`in e)?!1:Array.isArray(e.content)}async function x(t,n,r,i){let a=i?.previewToken?`projects/${n}/experiences/${r}/content?preview_token=${encodeURIComponent(i.previewToken)}`:`projects/${n}/experiences/${r}/content`,o;try{o=await e.t(t,a,i?.headers,i?.signal)}catch(e){return _(t)&&v(e)||`${r}`,null}if(!o.ok)return`${r}${o.status.toString()}`,null;let s;try{s=await o.json()}catch{return`${r}`,null}return b(s)?s:(`${r}`,null)}function S(e,t){for(let n of t.content)e.registerContent({id:n.id,contentModelKey:n.contentModelKey,data:n.data})}function C(e){if(typeof e!=`object`||!e||!(`projectConfig`in e)||!(`experienceContent`in e)||!(`manifestMetadata`in e))return!1;let{experienceContent:t}=e;return typeof t==`function`}async function w(){try{let e=await import(`virtual:picked/data`);return C(e)?e:null}catch{return null}}function T(e,t,n){return r=>x(e,t,r.id,n?{previewToken:n}:void 0)}function E(e,t){return n=>e(n,t?{previewToken:t}:void 0)}function D(e){return(t,n)=>e.experienceContent(t,n)}function O(e,t){let n=new Map;return(r,i)=>{let a=n.get(r.id);if(a)return a;let o=(async()=>{try{let n=await t(r,i);return n&&S(e,n),n}finally{n.delete(r.id)}})();return n.set(r.id,o),o}}function k(e,t){let n=new Set(t&&Array.isArray(t.experiences)?t.experiences.map(e=>e.id):[]);return(t,r)=>n.has(t.id)?e(t,r):Promise.resolve(null)}async function A(e){let{client:t,apiUrl:n,options:r}=e,i=p(t),a=!!i,o=r?.projectConfig??null,s=r?.getContent?E(r.getContent,i):null,c=null;if(i)return o??=await y(n,t.projectId,{previewToken:i}),s??=T(n,t.projectId,i),{config:o,contentLoader:s,dataSource:c,isPreview:a};if(o&&s)return{config:o,contentLoader:s,dataSource:c,isPreview:a};let l=await w();return l?(o??=l.projectConfig,s??=D(l),c=l.manifestMetadata,{config:o,contentLoader:s,dataSource:c,isPreview:a}):(o??=await y(n,t.projectId),s??=T(n,t.projectId),{config:o,contentLoader:s,dataSource:c,isPreview:a})}function j(e){return{name:`dynamic-experiences`,setup:n=>{let r=e?.apiUrl??n.apiUrl;return{onStart:(0,t.attach)({source:n.session.store.map(e=>e.id),effect:async t=>{let{config:i,contentLoader:a,dataSource:o,isPreview:s}=await A({client:n,apiUrl:r,options:e});a&&(n.contentLoader=O(n,k(a,i))),n.dataSource=o,i&&(n.previewEmbedderOrigins=i.previewEmbedderOrigins??null,f(n,i,{isPreview:s,sessionId:t}))}})}}}}Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return j}});
|
|
@@ -48,6 +48,28 @@ export interface ResolvedFeatureBucket extends FeatureBaseBucket {
|
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
50
|
export type FeatureBucket = UnresolvedFeatureBucket | ResolvedFeatureBucket;
|
|
51
|
+
export interface FeatureResult {
|
|
52
|
+
id: string;
|
|
53
|
+
bucket: string | boolean;
|
|
54
|
+
}
|
|
55
|
+
/** The bucket an evokable feature answers with, or undefined while its feature is unregistered. */
|
|
56
|
+
export type FeatureBucketValue = boolean | string | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Reads a bucket back out of its stored text.
|
|
59
|
+
*
|
|
60
|
+
* Storage holds a bucket as raw text, so this is the inverse of the write: `'true'` and
|
|
61
|
+
* `'false'` are the two booleans and every other value is a named variant. A variant named
|
|
62
|
+
* literally `true` or `false` therefore comes back as a boolean.
|
|
63
|
+
*
|
|
64
|
+
* @param {string} value - Stored text, or the value side of a `?picked-feature=` override.
|
|
65
|
+
* @returns {boolean | string} The boolean bucket, or the variant name unchanged.
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* parseBucket('true') // true
|
|
69
|
+
* parseBucket('variant-a') // 'variant-a'
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export declare function parseBucket(value: string): boolean | string;
|
|
51
73
|
declare const createFeatureIndexFactory: ({ client }: {
|
|
52
74
|
client: Picked;
|
|
53
75
|
}) => {
|
|
@@ -58,14 +80,15 @@ declare const createFeatureIndexFactory: ({ client }: {
|
|
|
58
80
|
getById: (id: string) => Store<FeatureBucket | undefined>;
|
|
59
81
|
getByName: (name: string) => Store<FeatureIndexItem | undefined>;
|
|
60
82
|
listStore: Store<FeatureBucket[]>;
|
|
61
|
-
getEvokableFeature: (featureName: string) => Store<() => Promise<
|
|
83
|
+
getEvokableFeature: (featureName: string) => Store<() => Promise<FeatureBucketValue>>;
|
|
84
|
+
getFeatureResult: (featureName: string) => Store<FeatureResult | undefined>;
|
|
62
85
|
};
|
|
63
86
|
/**
|
|
64
87
|
* Creates a feature index with lifecycle stores and registration logic.
|
|
65
88
|
*
|
|
66
89
|
* @template T - Factory parameter type.
|
|
67
90
|
* @param {T} params - Factory parameters including the client.
|
|
68
|
-
* @returns {ReturnType<typeof createFeatureIndexFactory>} The feature index with register, getById, getByName, listStore, and
|
|
91
|
+
* @returns {ReturnType<typeof createFeatureIndexFactory>} The feature index with register, getById, getByName, listStore, getEvokableFeature, and getFeatureResult methods.
|
|
69
92
|
* @example
|
|
70
93
|
* ```ts
|
|
71
94
|
* const features = createFeatureIndex({ client })
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature.d.ts","sourceRoot":"","sources":["../../../../src/entities/feature/feature.ts"],"names":[],"mappings":"AAAA,2GAA2G;AAC3G,OAAO,EAQL,KAAK,aAAa,EAElB,KAAK,KAAK,EACX,MAAM,UAAU,CAAA;AAEjB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAI1C,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACnE,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC7B,oGAAoG;IACpG,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,wHAAwH;IACxH,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAA;AAExE,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,OAAO,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;CAClC;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,OAAO,GAAG,MAAM,CAAA;IACxB,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAC9B;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,EAAE,EAAE,MAAM,CAAA;IACV,oGAAoG;IACpG,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,wHAAwH;IACxH,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,uBAAwB,SAAQ,iBAAiB;IAChE,UAAU,EAAE,KAAK,CAAA;IACjB,SAAS,EAAE,MAAM,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC,CAAA;CACnE;AAED,MAAM,WAAW,qBAAsB,SAAQ,iBAAiB;IAC9D,UAAU,EAAE,IAAI,CAAA;IAChB,SAAS,EAAE,MAAM;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAA;CAC1D;AAED,MAAM,MAAM,aAAa,GAAG,uBAAuB,GAAG,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"feature.d.ts","sourceRoot":"","sources":["../../../../src/entities/feature/feature.ts"],"names":[],"mappings":"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"}
|
package/dist/types/picked.d.ts
CHANGED
|
@@ -155,7 +155,8 @@ export declare class Picked {
|
|
|
155
155
|
getById: (id: string) => Store<import(".").FeatureBucket | undefined>;
|
|
156
156
|
getByName: (name: string) => Store<import(".").FeatureIndexItem | undefined>;
|
|
157
157
|
listStore: Store<import(".").FeatureBucket[]>;
|
|
158
|
-
getEvokableFeature: (featureName: string) => Store<() => Promise<
|
|
158
|
+
getEvokableFeature: (featureName: string) => Store<() => Promise<import(".").FeatureBucketValue>>;
|
|
159
|
+
getFeatureResult: (featureName: string) => Store<import(".").FeatureResult | undefined>;
|
|
159
160
|
};
|
|
160
161
|
readonly conditions: {
|
|
161
162
|
register: (condition: Condition) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"picked.d.ts","sourceRoot":"","sources":["../../src/picked.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"picked.d.ts","sourceRoot":"","sources":["../../src/picked.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/dist/docs/actions.mdx
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: docs
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
import { Screenshot } from '../../components/Screenshot'
|
|
6
|
-
|
|
7
|
-
# Actions
|
|
8
|
-
|
|
9
|
-
An action is a side effect that starts when the flow reaches it. Use an action to
|
|
10
|
-
track an event, to send data to an external service, or to call a webhook.
|
|
11
|
-
|
|
12
|
-
<Screenshot
|
|
13
|
-
route="/{orgSlug}/{projectId}/workspaces/{workspaceId}/actions"
|
|
14
|
-
alt="The actions list for a workspace on the Picked dashboard"
|
|
15
|
-
/>
|
|
16
|
-
|
|
17
|
-
## Create an action
|
|
18
|
-
|
|
19
|
-
1. Open your project.
|
|
20
|
-
2. Click **Actions** in the sidebar.
|
|
21
|
-
3. Click **New Action**.
|
|
22
|
-
4. Enter a name and a key.
|
|
23
|
-
5. Click **Create**.
|
|
24
|
-
|
|
25
|
-
The key is a unique identifier for your application. You set it once, and you cannot
|
|
26
|
-
change it later.
|
|
27
|
-
|
|
28
|
-
## Set up an action
|
|
29
|
-
|
|
30
|
-
**Name**: The name that the dashboard shows. Your visitors do not see it.
|
|
31
|
-
|
|
32
|
-
**Key**: The identifier that your application uses for this action. Your visitors do
|
|
33
|
-
not see it.
|
|
34
|
-
|
|
35
|
-
## Register in your application
|
|
36
|
-
|
|
37
|
-
Register your actions when you create the Picked client. Pass an `actions` object.
|
|
38
|
-
Each key in it must match an action key from the dashboard:
|
|
39
|
-
|
|
40
|
-
```typescript
|
|
41
|
-
import { createClient } from '@picked/client'
|
|
42
|
-
|
|
43
|
-
const picked = createClient({
|
|
44
|
-
projectId: 'your-project-id',
|
|
45
|
-
actions: {
|
|
46
|
-
'track-signup': () => {
|
|
47
|
-
analytics.track('signup_completed')
|
|
48
|
-
},
|
|
49
|
-
'notify': (params) => {
|
|
50
|
-
sendNotification(params)
|
|
51
|
-
},
|
|
52
|
-
'check-eligibility': async () => {
|
|
53
|
-
const response = await fetch('/api/eligibility')
|
|
54
|
-
// Throw only when the request itself fails. That takes the failure branch.
|
|
55
|
-
if (!response.ok) throw new Error('Eligibility request failed')
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
})
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
Each action is a function. It takes optional parameters and it usually runs a side
|
|
62
|
-
effect. When the flow reaches an action node, the SDK calls the function that
|
|
63
|
-
matches. The SDK then takes a branch, which depends on whether the function succeeds
|
|
64
|
-
or throws. See [Success and failure branches](#success-and-failure-branches).
|
|
65
|
-
|
|
66
|
-
See [SDK Actions](/sdk/actions) for more detail.
|
|
67
|
-
|
|
68
|
-
## Use actions in flows
|
|
69
|
-
|
|
70
|
-
In the flow builder, drag an action from the entity browser onto the canvas. Connect
|
|
71
|
-
it to the point in the flow where you want it to start.
|
|
72
|
-
|
|
73
|
-
An action runs when the flow reaches its node. It does not interrupt your visitor. By
|
|
74
|
-
default the flow continues to the next connected node.
|
|
75
|
-
|
|
76
|
-
### Success and failure branches
|
|
77
|
-
|
|
78
|
-
An action node can have two outgoing branches: **success** and **failure**. The SDK
|
|
79
|
-
chooses the branch from the outcome of the action:
|
|
80
|
-
|
|
81
|
-
- **Failure** — the action throws, or its promise rejects. The flow takes the failure
|
|
82
|
-
branch.
|
|
83
|
-
- **Success** — the action resolves to any value: nothing, `true`, `false`, or a
|
|
84
|
-
string. A returned `false` is a valid response and not a failure. The flow takes
|
|
85
|
-
the success branch.
|
|
86
|
-
|
|
87
|
-
Keep the failure branch for a true error. Throw on the failure case, for example
|
|
88
|
-
`if (!response.ok) throw new Error(...)`. A valid negative result is _not_ a failure.
|
|
89
|
-
An API that returns `200` with `{ serviced: false }` must record that value as a
|
|
90
|
-
response. Branch on it with a condition instead of a throw.
|
|
91
|
-
|
|
92
|
-
An action node can also have one plain connection, with no success or failure branch.
|
|
93
|
-
The flow then continues through it on either outcome.
|
|
94
|
-
|
|
95
|
-
## Reuse actions
|
|
96
|
-
|
|
97
|
-
An action is a project-level entity. Use the same action in more than one experience
|
|
98
|
-
flow. A change to the options of an action applies at every place that uses it.
|
|
@@ -1,403 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: docs
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Authentication
|
|
6
|
-
|
|
7
|
-
The Picked API supports four ways to authenticate. They are a session from an email
|
|
8
|
-
address and a password, an OAuth provider, a magic link, and an API key. This guide
|
|
9
|
-
covers each one. It also covers how to control a session and how to use multi-factor
|
|
10
|
-
authentication (MFA).
|
|
11
|
-
|
|
12
|
-
## Sign in with an email address and a password
|
|
13
|
-
|
|
14
|
-
The `sessionCreate` mutation authenticates a user from an email address and a
|
|
15
|
-
password. It returns a session.
|
|
16
|
-
|
|
17
|
-
```graphql
|
|
18
|
-
mutation {
|
|
19
|
-
sessionCreate(input: {
|
|
20
|
-
email: "user@example.com"
|
|
21
|
-
password: "secure-password"
|
|
22
|
-
}) {
|
|
23
|
-
session {
|
|
24
|
-
accessToken
|
|
25
|
-
refreshToken
|
|
26
|
-
expiresAt
|
|
27
|
-
user {
|
|
28
|
-
id
|
|
29
|
-
email
|
|
30
|
-
}
|
|
31
|
-
aal
|
|
32
|
-
}
|
|
33
|
-
requiresMfa
|
|
34
|
-
mfaFactors {
|
|
35
|
-
id
|
|
36
|
-
factorType
|
|
37
|
-
status
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
When the user has MFA on, the response sets `requiresMfa` to `true` and returns the
|
|
44
|
-
`mfaFactors` of that user. The caller must then complete an MFA challenge before it
|
|
45
|
-
receives a full session. See [MFA](#multi-factor-authentication-mfa) below.
|
|
46
|
-
|
|
47
|
-
When MFA is off, the response holds a `session` with an `accessToken`, a
|
|
48
|
-
`refreshToken`, and an `expiresAt` timestamp.
|
|
49
|
-
|
|
50
|
-
## Create an account
|
|
51
|
-
|
|
52
|
-
The `accountCreate` mutation creates a new account:
|
|
53
|
-
|
|
54
|
-
```graphql
|
|
55
|
-
mutation {
|
|
56
|
-
accountCreate(input: {
|
|
57
|
-
email: "newuser@example.com"
|
|
58
|
-
password: "secure-password"
|
|
59
|
-
metadata: { firstName: "Jane", lastName: "Doe" }
|
|
60
|
-
}) {
|
|
61
|
-
user {
|
|
62
|
-
id
|
|
63
|
-
email
|
|
64
|
-
}
|
|
65
|
-
session {
|
|
66
|
-
accessToken
|
|
67
|
-
refreshToken
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
The `metadata` field is optional. It takes any JSON, and you can hold profile
|
|
74
|
-
information in it. When the account needs email verification, the session in the
|
|
75
|
-
response is `null` until the user verifies the email address.
|
|
76
|
-
|
|
77
|
-
## Verify an email address
|
|
78
|
-
|
|
79
|
-
After you create the account, the user receives a verification email with a token.
|
|
80
|
-
The `accountVerifyEmail` mutation completes the verification:
|
|
81
|
-
|
|
82
|
-
```graphql
|
|
83
|
-
mutation {
|
|
84
|
-
accountVerifyEmail(input: {
|
|
85
|
-
email: "newuser@example.com"
|
|
86
|
-
token: "verification-token-from-email"
|
|
87
|
-
}) {
|
|
88
|
-
session {
|
|
89
|
-
accessToken
|
|
90
|
-
refreshToken
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
To send the verification email again:
|
|
97
|
-
|
|
98
|
-
```graphql
|
|
99
|
-
mutation {
|
|
100
|
-
accountResendVerification(input: {
|
|
101
|
-
email: "newuser@example.com"
|
|
102
|
-
}) {
|
|
103
|
-
success
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
## The OAuth flow with Google
|
|
109
|
-
|
|
110
|
-
The API supports Google as an OAuth provider. The flow has two steps.
|
|
111
|
-
|
|
112
|
-
### Step 1: get the authorization URL
|
|
113
|
-
|
|
114
|
-
```graphql
|
|
115
|
-
mutation {
|
|
116
|
-
oauthAuthorize(input: {
|
|
117
|
-
provider: GOOGLE
|
|
118
|
-
redirectUrl: "https://app.example.com/auth/callback"
|
|
119
|
-
scopes: ["openid", "email", "profile"]
|
|
120
|
-
}) {
|
|
121
|
-
url
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
The caller sends the user to the `url` in the response. The user authenticates with
|
|
127
|
-
Google. Google then sends the user back to a URL on the same dashboard deployment,
|
|
128
|
-
with a `code` parameter. The caller exchanges that code for a session.
|
|
129
|
-
|
|
130
|
-
### Step 2: exchange the code for a session
|
|
131
|
-
|
|
132
|
-
```graphql
|
|
133
|
-
mutation {
|
|
134
|
-
oauthCallback(input: {
|
|
135
|
-
provider: GOOGLE
|
|
136
|
-
code: "auth-code-from-google"
|
|
137
|
-
}) {
|
|
138
|
-
session {
|
|
139
|
-
accessToken
|
|
140
|
-
refreshToken
|
|
141
|
-
expiresAt
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
## Magic links
|
|
148
|
-
|
|
149
|
-
A magic link authenticates a user through an email address, with no password.
|
|
150
|
-
|
|
151
|
-
### Send a magic link
|
|
152
|
-
|
|
153
|
-
```graphql
|
|
154
|
-
mutation {
|
|
155
|
-
magicLinkSend(input: {
|
|
156
|
-
email: "user@example.com"
|
|
157
|
-
redirectUrl: "https://app.example.com/auth/verify"
|
|
158
|
-
}) {
|
|
159
|
-
success
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
The user receives an email with a link, and the link holds a token.
|
|
165
|
-
|
|
166
|
-
### Verify the magic link
|
|
167
|
-
|
|
168
|
-
```graphql
|
|
169
|
-
mutation {
|
|
170
|
-
magicLinkVerify(input: {
|
|
171
|
-
email: "user@example.com"
|
|
172
|
-
token: "token-from-magic-link"
|
|
173
|
-
}) {
|
|
174
|
-
session {
|
|
175
|
-
accessToken
|
|
176
|
-
refreshToken
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
## Passwords
|
|
183
|
-
|
|
184
|
-
### Reset a password
|
|
185
|
-
|
|
186
|
-
Send an email to reset the password:
|
|
187
|
-
|
|
188
|
-
```graphql
|
|
189
|
-
mutation {
|
|
190
|
-
passwordResetSend(input: {
|
|
191
|
-
email: "user@example.com"
|
|
192
|
-
redirectUrl: "https://app.example.com/reset-password"
|
|
193
|
-
}) {
|
|
194
|
-
success
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
Complete the reset with the token from that email:
|
|
200
|
-
|
|
201
|
-
```graphql
|
|
202
|
-
mutation {
|
|
203
|
-
passwordReset(input: {
|
|
204
|
-
email: "user@example.com"
|
|
205
|
-
token: "reset-token-from-email"
|
|
206
|
-
newPassword: "new-secure-password"
|
|
207
|
-
}) {
|
|
208
|
-
session {
|
|
209
|
-
accessToken
|
|
210
|
-
refreshToken
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
### Change a password
|
|
217
|
-
|
|
218
|
-
This mutation needs authentication:
|
|
219
|
-
|
|
220
|
-
```graphql
|
|
221
|
-
mutation {
|
|
222
|
-
passwordUpdate(input: {
|
|
223
|
-
currentPassword: "old-password"
|
|
224
|
-
newPassword: "new-secure-password"
|
|
225
|
-
}) {
|
|
226
|
-
success
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
## Multi-factor authentication (MFA)
|
|
232
|
-
|
|
233
|
-
MFA adds a second layer of security, and it uses a telephone to verify the user. The
|
|
234
|
-
API can add an MFA factor, send a challenge, verify a challenge, and remove a factor.
|
|
235
|
-
Every MFA mutation needs authentication.
|
|
236
|
-
|
|
237
|
-
### Add a factor
|
|
238
|
-
|
|
239
|
-
```graphql
|
|
240
|
-
mutation {
|
|
241
|
-
mfaFactorEnroll(input: {
|
|
242
|
-
factorType: PHONE
|
|
243
|
-
phone: "+15551234567"
|
|
244
|
-
friendlyName: "My Phone"
|
|
245
|
-
}) {
|
|
246
|
-
factor {
|
|
247
|
-
id
|
|
248
|
-
factorType
|
|
249
|
-
status
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
A new factor has the status `UNVERIFIED` until a challenge confirms it.
|
|
256
|
-
|
|
257
|
-
### Send a challenge
|
|
258
|
-
|
|
259
|
-
```graphql
|
|
260
|
-
mutation {
|
|
261
|
-
mfaChallengeSend(input: {
|
|
262
|
-
factorId: "factor-id"
|
|
263
|
-
}) {
|
|
264
|
-
challengeId
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
This sends a verification code to the telephone number of the factor.
|
|
270
|
-
|
|
271
|
-
### Verify the challenge
|
|
272
|
-
|
|
273
|
-
```graphql
|
|
274
|
-
mutation {
|
|
275
|
-
mfaChallengeVerify(input: {
|
|
276
|
-
factorId: "factor-id"
|
|
277
|
-
challengeId: "challenge-id"
|
|
278
|
-
code: "123456"
|
|
279
|
-
}) {
|
|
280
|
-
session {
|
|
281
|
-
accessToken
|
|
282
|
-
refreshToken
|
|
283
|
-
aal
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
On success, the session moves to Authenticator Assurance Level `AAL2`. The status of
|
|
290
|
-
the factor changes to `VERIFIED`.
|
|
291
|
-
|
|
292
|
-
### Remove a factor
|
|
293
|
-
|
|
294
|
-
```graphql
|
|
295
|
-
mutation {
|
|
296
|
-
mfaFactorUnenroll(input: {
|
|
297
|
-
factorId: "factor-id"
|
|
298
|
-
}) {
|
|
299
|
-
success
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
## Use a session
|
|
305
|
-
|
|
306
|
-
After the caller has a session, it puts the access token in the `Authorization`
|
|
307
|
-
header of every request that needs authentication:
|
|
308
|
-
|
|
309
|
-
```
|
|
310
|
-
Authorization: Bearer <accessToken>
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
The `expiresAt` field of the session gives the time at which the access token
|
|
314
|
-
expires. The caller must refresh the session before that time.
|
|
315
|
-
|
|
316
|
-
### Authenticator assurance levels
|
|
317
|
-
|
|
318
|
-
The session holds an `aal` field, and it gives the strength of the authentication:
|
|
319
|
-
|
|
320
|
-
| Level | Meaning |
|
|
321
|
-
|-------|---------|
|
|
322
|
-
| `AAL1` | One factor: an email address and a password, OAuth, or a magic link |
|
|
323
|
-
| `AAL2` | More than one factor: the user completed an MFA challenge |
|
|
324
|
-
|
|
325
|
-
Some operations need `AAL2`. When a caller at `AAL1` tries one of them, the API
|
|
326
|
-
returns an authorization error.
|
|
327
|
-
|
|
328
|
-
## Refresh a session
|
|
329
|
-
|
|
330
|
-
An access token has a short life. The `sessionRefresh` mutation exchanges a refresh
|
|
331
|
-
token for a new session:
|
|
332
|
-
|
|
333
|
-
```graphql
|
|
334
|
-
mutation {
|
|
335
|
-
sessionRefresh(input: {
|
|
336
|
-
refreshToken: "v1.refresh-token..."
|
|
337
|
-
}) {
|
|
338
|
-
session {
|
|
339
|
-
accessToken
|
|
340
|
-
refreshToken
|
|
341
|
-
expiresAt
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
The response holds a new `accessToken` and a new `refreshToken`. The API invalidates
|
|
348
|
-
the earlier refresh token. This mutation needs no `Authorization` header.
|
|
349
|
-
|
|
350
|
-
## API key authentication
|
|
351
|
-
|
|
352
|
-
An API key gives access to the API for a long time, inside a set of scopes. Most
|
|
353
|
-
callers use an API key for a server-to-server integration or for an automated
|
|
354
|
-
workflow.
|
|
355
|
-
|
|
356
|
-
To authenticate with an API key, include it in the `x-api-key` header:
|
|
357
|
-
|
|
358
|
-
```
|
|
359
|
-
x-api-key: pk_live_abc123...
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
An API key belongs to an organization, and it can also belong to one project. It
|
|
363
|
-
carries a set of [authorization scopes](./authorization-and-scopes.md), and those
|
|
364
|
-
scopes decide which operations the key can do.
|
|
365
|
-
|
|
366
|
-
See [API Keys](/api-keys) for how to control a key from the dashboard.
|
|
367
|
-
|
|
368
|
-
### Create an API key
|
|
369
|
-
|
|
370
|
-
The `apiKeyCreate` mutation creates a new API key. Only a user with a session can
|
|
371
|
-
call it. Another API key cannot:
|
|
372
|
-
|
|
373
|
-
```graphql
|
|
374
|
-
mutation {
|
|
375
|
-
apiKeyCreate(input: {
|
|
376
|
-
organizationId: "org-id"
|
|
377
|
-
name: "CI/CD Pipeline Key"
|
|
378
|
-
projectId: "project-id"
|
|
379
|
-
scopes: [ORGANIZATION_READ, ORGANIZATION_PROJECTS_READ]
|
|
380
|
-
}) {
|
|
381
|
-
apiKey
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
```
|
|
385
|
-
|
|
386
|
-
The response holds the full API key string one time only. Keep it in a secure place, because
|
|
387
|
-
you cannot read it again.
|
|
388
|
-
|
|
389
|
-
The scopes that you ask for must all be scopes of the user who creates the key. See
|
|
390
|
-
[Authorization and Scopes](./authorization-and-scopes.md) for more detail.
|
|
391
|
-
|
|
392
|
-
### Revoke an API key
|
|
393
|
-
|
|
394
|
-
```graphql
|
|
395
|
-
mutation {
|
|
396
|
-
apiKeyRevoke(input: {
|
|
397
|
-
keyId: "key-id"
|
|
398
|
-
organizationId: "org-id"
|
|
399
|
-
})
|
|
400
|
-
}
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
The API invalidates a revoked key immediately. No later request can use it.
|