diff --git a/README.md b/README.md index 79829d0..13e0bf8 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ This repository contains examples of [embedding Observable notebooks](https://ob | [**custom-fluid-width**](https://github.com/observablehq/examples/tree/main/custom-fluid-width/) | Resize a chart when the window is resized | | [**custom-fluid-width-and-height**](https://github.com/observablehq/examples/tree/main/custom-fluid-width-and-height/) | Resize a chart when its container is resized | | [**custom-library**](https://github.com/observablehq/examples/tree/main/custom-library/) | Override the Observable Standard Library | +| [**secret**](https://github.com/observablehq/examples/tree/main/secret) | Override the implementation of Secrets | | [**standalone**](https://github.com/observablehq/examples/tree/main/standalone/) | Self-host an Observable notebook with no external dependencies | | [**versioning**](https://github.com/observablehq/examples/tree/main/versioning/) | Embed a specific version of a notebook | | [**iframe-resize**](https://github.com/observablehq/examples/tree/main/iframe-resize/) | Implementing Embedly’s protocol for Iframes that resize to match their contents | diff --git a/secret/9cdbbe083c4d48f4@9.js b/secret/9cdbbe083c4d48f4@9.js new file mode 100644 index 0000000..d49d79a --- /dev/null +++ b/secret/9cdbbe083c4d48f4@9.js @@ -0,0 +1,7 @@ +export default function define(runtime, observer) { + const main = runtime.module(); + main.variable(observer()).define(["Secret"], function(Secret){return( +Secret("MY_SECRET_KEY") +)}); + return main; +} diff --git a/secret/README.md b/secret/README.md new file mode 100644 index 0000000..26a2e22 --- /dev/null +++ b/secret/README.md @@ -0,0 +1,19 @@ +# Observable Example: Secret + +See it live: https://observablehq.github.io/examples/secret + +Observable lets you configure [Secrets](https://observablehq.com/@observablehq/secrets). Sensitive variables can be stored outside your code and returned by calling `Secret("MY_SECRET_KEY")`, which might return a password like `"$w0rdf1sh"`. If you publish the notebook, the Secret will throw an error instead of returning a value, so that the Secret is not publicly exposed. + +Calling `Secret` will also throw an error if you download the notebook — but sometimes, you might be downloading it to run in your own secure setting where you’d like to set the Secret a different way. This example shows how to use your own implementation of the Secret function to provide things like environment variables or API keys without rewriting your code. + +In this _insecure_ example, index.html gets Secret values from a hardcoded Map. This should never be used in code that would be seen openly on the client side; if you published this index.html publicly on the Web, anyone could read your hardcoded Secrets. + +```js +const secrets = new Map([["MY_SECRET_KEY", "$w0rdf1sh"]]); +const Secret = () => key => secrets.get(key); +const runtime = new Runtime(Object.assign(new Library, {Secret})); +``` + +Note that our `Secret` is a function that returns the function that gets called by the cell; the [Runtime documentation](https://github.com/observablehq/runtime) says: + +> If you wish for the value of a builtin to be a function, the builtin must be defined either as a promise that resolves to a function or as a function that returns a function. Builtins may also be defined as generators for dynamic values… diff --git a/secret/index.html b/secret/index.html new file mode 100644 index 0000000..8330d6c --- /dev/null +++ b/secret/index.html @@ -0,0 +1,46 @@ + + +
This example demonstrates overriding Secrets with your own implementation.
+ + diff --git a/secret/index.js b/secret/index.js new file mode 100644 index 0000000..090106a --- /dev/null +++ b/secret/index.js @@ -0,0 +1 @@ +export {default} from "./9cdbbe083c4d48f4@9.js"; diff --git a/secret/inspector.css b/secret/inspector.css new file mode 100644 index 0000000..278bfae --- /dev/null +++ b/secret/inspector.css @@ -0,0 +1 @@ +:root{--syntax_normal:#1b1e23;--syntax_comment:#a9b0bc;--syntax_number:#20a5ba;--syntax_keyword:#c30771;--syntax_atom:#10a778;--syntax_string:#008ec4;--syntax_error:#ffbedc;--syntax_unknown_variable:#838383;--syntax_known_variable:#005f87;--syntax_matchbracket:#20bbfc;--syntax_key:#6636b4;--mono_fonts:82%/1.5 Menlo,Consolas,monospace}.observablehq--collapsed,.observablehq--expanded,.observablehq--function,.observablehq--gray,.observablehq--import,.observablehq--string:after,.observablehq--string:before{color:var(--syntax_normal)}.observablehq--collapsed,.observablehq--inspect a{cursor:pointer}.observablehq--field{text-indent:-1em;margin-left:1em}.observablehq--empty{color:var(--syntax_comment)}.observablehq--blue,.observablehq--keyword{color:#3182bd}.observablehq--forbidden,.observablehq--pink{color:#e377c2}.observablehq--orange{color:#e6550d}.observablehq--boolean,.observablehq--null,.observablehq--undefined{color:var(--syntax_atom)}.observablehq--bigint,.observablehq--date,.observablehq--green,.observablehq--number,.observablehq--regexp,.observablehq--symbol{color:var(--syntax_number)}.observablehq--index,.observablehq--key{color:var(--syntax_key)}.observablehq--prototype-key{color:#aaa}.observablehq--empty{font-style:oblique}.observablehq--purple,.observablehq--string{color:var(--syntax_string)}.observablehq--error,.observablehq--red{color:#e7040f}.observablehq--inspect{font:var(--mono_fonts);overflow-x:auto;display:block;white-space:pre}.observablehq--error .observablehq--inspect{word-break:break-all;white-space:pre-wrap} \ No newline at end of file diff --git a/secret/package.json b/secret/package.json new file mode 100644 index 0000000..c39e122 --- /dev/null +++ b/secret/package.json @@ -0,0 +1,14 @@ +{ + "name": "9cdbbe083c4d48f4", + "main": "9cdbbe083c4d48f4@9.js", + "version": "9.0.0", + "homepage": "https://observablehq.com/d/9cdbbe083c4d48f4", + "author": { + "name": "tophtest", + "url": "https://observablehq.com/@tophtest" + }, + "type": "module", + "peerDependencies": { + "@observablehq/runtime": "4" + } +} \ No newline at end of file diff --git a/secret/runtime.js b/secret/runtime.js new file mode 100644 index 0000000..6ee9501 --- /dev/null +++ b/secret/runtime.js @@ -0,0 +1,2 @@ +// @observablehq/runtime v4.17.4 Copyright 2021 Observable, Inc. +function e(e,t,n){n=n||{};var r=e.ownerDocument,o=r.defaultView.CustomEvent;"function"==typeof o?o=new o(t,{detail:n}):((o=r.createEvent("Event")).initEvent(t,!1,!1),o.detail=n),e.dispatchEvent(o)}function t(e){return Array.isArray(e)||e instanceof Int8Array||e instanceof Int16Array||e instanceof Int32Array||e instanceof Uint8Array||e instanceof Uint8ClampedArray||e instanceof Uint16Array||e instanceof Uint32Array||e instanceof Float32Array||e instanceof Float64Array}function n(e){return e===(0|e)+""}function r(e){const t=document.createElement("span");return t.className="observablehq--cellname",t.textContent=`${e} = `,t}const o=Symbol.prototype.toString;function i(e){return o.call(e)}const{getOwnPropertySymbols:a,prototype:{hasOwnProperty:s}}=Object,{toStringTag:l}=Symbol,u={},c=a;function d(e,t){return s.call(e,t)}function f(e){return e[l]||e.constructor&&e.constructor.name||"Object"}function h(e,t){try{const n=e[t];return n&&n.constructor,n}catch(e){return u}}const p=[{symbol:"@@__IMMUTABLE_INDEXED__@@",name:"Indexed",modifier:!0},{symbol:"@@__IMMUTABLE_KEYED__@@",name:"Keyed",modifier:!0},{symbol:"@@__IMMUTABLE_LIST__@@",name:"List",arrayish:!0},{symbol:"@@__IMMUTABLE_MAP__@@",name:"Map"},{symbol:"@@__IMMUTABLE_ORDERED__@@",name:"Ordered",modifier:!0,prefix:!0},{symbol:"@@__IMMUTABLE_RECORD__@@",name:"Record"},{symbol:"@@__IMMUTABLE_SET__@@",name:"Set",arrayish:!0,setish:!0},{symbol:"@@__IMMUTABLE_STACK__@@",name:"Stack",arrayish:!0}];function m(e){try{let t=p.filter((({symbol:t})=>!0===e[t]));if(!t.length)return;const n=t.find((e=>!e.modifier)),r="Map"===n.name&&t.find((e=>e.modifier&&e.prefix)),o=t.some((e=>e.arrayish)),i=t.some((e=>e.setish));return{name:`${r?r.name:""}${n.name}`,symbols:t,arrayish:o&&!i,setish:i}}catch(e){return null}}const{getPrototypeOf:v,getOwnPropertyDescriptors:b}=Object,_=v({});function w(n,o,i,a){let s,l,u,c,d=t(n);n instanceof Map?n instanceof n.constructor?(s=`Map(${n.size})`,l=y):(s="Map()",l=N):n instanceof Set?n instanceof n.constructor?(s=`Set(${n.size})`,l=g):(s="Set()",l=N):d?(s=`${n.constructor.name}(${n.length})`,l=E):(c=m(n))?(s=`Immutable.${c.name}${"Record"===c.name?"":`(${n.size})`}`,d=c.arrayish,l=c.arrayish?C:c.setish?x:$):a?(s=f(n),l=j):(s=f(n),l=N);const h=document.createElement("span");h.className="observablehq--expanded",i&&h.appendChild(r(i));const p=h.appendChild(document.createElement("a"));p.innerHTML="",p.appendChild(document.createTextNode(`${s}${d?" [":" {"}`)),p.addEventListener("mouseup",(function(e){e.stopPropagation(),ae(h,O(n,null,i,a))})),l=l(n);for(let e=0;!(u=l.next()).done&&e<20;++e)h.appendChild(u.value);if(!u.done){const t=h.appendChild(document.createElement("a"));t.className="observablehq--field",t.style.display="block",t.appendChild(document.createTextNode(" … more")),t.addEventListener("mouseup",(function(t){t.stopPropagation(),h.insertBefore(u.value,h.lastChild.previousSibling);for(let e=0;!(u=l.next()).done&&e<19;++e)h.insertBefore(u.value,h.lastChild.previousSibling);u.done&&h.removeChild(h.lastChild.previousSibling),e(h,"load")}))}return h.appendChild(document.createTextNode(d?"]":"}")),h}function*y(e){for(const[t,n]of e)yield q(t,n);yield*N(e)}function*g(e){for(const t of e)yield A(t);yield*N(e)}function*x(e){for(const t of e)yield A(t)}function*E(e){for(let t=0,n=e.length;t{t=e}))},value:{get:()=>e,set:n=>t(e=n)}}),void 0!==e&&t(e)}function*Tt(){for(;;)yield Date.now()}var Ot=new Map;function Mt(e,t){var n;return(n=Ot.get(e=+e))?n.then((()=>t)):(n=Date.now())>=e?Promise.resolve(t):function(e,t){var n=new Promise((function(n){Ot.delete(t);var r=t-e;if(!(r>0))throw new Error("invalid time");if(r>2147483647)throw new Error("too long to wait");setTimeout(n,r)}));return Ot.set(t,n),n}(n,e).then((()=>t))}var Lt={delay:function(e,t){return new Promise((function(n){setTimeout((function(){n(t)}),e)}))},tick:function(e,t){return Mt(Math.ceil((Date.now()+1)/e)*e,t)},when:Mt};function kt(e,t){if(/^(\w+:)|\/\//i.test(e))return e;if(/^[.]{0,2}\//i.test(e))return new URL(e,null==t?location:t).href;if(!e.length||/^[\s._]/.test(e)||/\s$/.test(e))throw new Error("illegal name");return"https://unpkg.com/"+e}function Ut(e){return null==e?ke:Ue(e)}var Rt=St((function(e){var t=document.createElementNS("http://www.w3.org/2000/svg","g");return t.innerHTML=e.trim(),t}),(function(){return document.createElementNS("http://www.w3.org/2000/svg","g")})),Dt=String.raw;function Ft(){return Nt((function(e){var t=e(document.body.clientWidth);function n(){var n=document.body.clientWidth;n!==t&&e(t=n)}return window.addEventListener("resize",n),function(){window.removeEventListener("resize",n)}}))}var It=Object.assign((function(e){const t=Ut(e);var n;Object.defineProperties(this,(n={FileAttachment:()=>_t,Arrow:()=>t(rt.resolve()),Inputs:()=>t(He.resolve()),Mutable:()=>At,Plot:()=>t(We.resolve()),SQLite:()=>st(t),SQLiteDatabaseClient:()=>SQLiteDatabaseClient,_:()=>t(Ye.resolve()),aq:()=>t.alias({"apache-arrow":rt.resolve()})(ot.resolve()),d3:()=>t(Be.resolve()),dot:()=>t(Ze.resolve()),htl:()=>t(Ge.resolve()),html:()=>qt,md:()=>function(e){return e(Qe.resolve()).then((function(t){return St((function(n){var r=document.createElement("div");r.innerHTML=t(n,{langPrefix:""}).trim();var o=r.querySelectorAll("pre code[class]");return o.length>0&&e(Ve.resolve()).then((function(t){o.forEach((function(n){function r(){t.highlightBlock(n),n.parentNode.classList.add("observablehq--md-pre")}t.getLanguage(n.className)?r():e(Ve.resolve("async-languages/index.js")).then((r=>{if(r.has(n.className))return e(Ve.resolve("async-languages/"+r.get(n.className))).then((e=>{t.registerLanguage(n.className,e)}))})).then(r,r)}))})),r}),(function(){return document.createElement("div")}))}))}(t),now:Tt,require:()=>t,resolve:()=>kt,svg:()=>Rt,tex:()=>function(e){return Promise.all([e(Je.resolve()),(t=Je.resolve("dist/katex.min.css"),new Promise((function(e,n){var r=document.createElement("link");r.rel="stylesheet",r.href=t,r.onerror=n,r.onload=e,document.head.appendChild(r)})))]).then((function(e){var t=e[0],n=r();function r(e){return function(){var n=document.createElement("div");return t.render(Dt.apply(String,arguments),n,e),n.removeChild(n.firstChild)}}return n.options=r,n.block=r({displayMode:!0}),n}));var t}(t),topojson:()=>t(it.resolve()),vl:()=>async function(e){const[t,n,r]=await Promise.all([et,tt,nt].map((t=>e(t.resolve()))));return r.register(t,n)}(t),width:Ft,DOM:xt,Files:Et,Generators:Pt,Promises:Lt},Object.fromEntries(Object.entries(n).map(zt))))}),{resolve:ke.resolve});function zt([e,t]){return[e,{value:t,writable:!0,enumerable:!0}]}function Bt(e,t){this.message=e+"",this.input=t}Bt.prototype=Object.create(Error.prototype),Bt.prototype.name="RuntimeError",Bt.prototype.constructor=Bt;var Ht=Array.prototype,Wt=Ht.map,Zt=Ht.forEach;function Vt(e){return function(){return e}}function Jt(e){return e}function Yt(){}var Gt={};function Kt(e,t,n){var r;n||(n=Gt),Object.defineProperties(this,{_observer:{value:n,writable:!0},_definition:{value:en,writable:!0},_duplicate:{value:void 0,writable:!0},_duplicates:{value:void 0,writable:!0},_indegree:{value:NaN,writable:!0},_inputs:{value:[],writable:!0},_invalidate:{value:Yt,writable:!0},_module:{value:t},_name:{value:null,writable:!0},_outputs:{value:new Set,writable:!0},_promise:{value:Promise.resolve(void 0),writable:!0},_reachable:{value:n!==Gt,writable:!0},_rejector:{value:(r=this,function(e){if(e===en)throw new Bt(r._name+" is not defined",r._name);if(e instanceof Error&&e.message)throw new Bt(e.message,r._name);throw new Bt(r._name+" could not be resolved",r._name)})},_type:{value:e},_value:{value:void 0,writable:!0},_version:{value:0,writable:!0}})}function Qt(e){e._module._runtime._dirty.add(e),e._outputs.add(this)}function Xt(e){e._module._runtime._dirty.add(e),e._outputs.delete(this)}function en(){throw en}function tn(e){return function(){throw new Bt(e+" is defined more than once")}}function nn(e,t,n){var r=this._module._scope,o=this._module._runtime;if(this._inputs.forEach(Xt,this),t.forEach(Qt,this),this._inputs=t,this._definition=n,this._value=void 0,n===Yt?o._variables.delete(this):o._variables.add(this),e!==this._name||r.get(e)!==this){var i,a;if(this._name)if(this._outputs.size)r.delete(this._name),(a=this._module._resolve(this._name))._outputs=this._outputs,this._outputs=new Set,a._outputs.forEach((function(e){e._inputs[e._inputs.indexOf(this)]=a}),this),a._outputs.forEach(o._updates.add,o._updates),o._dirty.add(a).add(this),r.set(this._name,a);else if((a=r.get(this._name))===this)r.delete(this._name);else{if(3!==a._type)throw new Error;a._duplicates.delete(this),this._duplicate=void 0,1===a._duplicates.size&&(a=a._duplicates.keys().next().value,i=r.get(this._name),a._outputs=i._outputs,i._outputs=new Set,a._outputs.forEach((function(e){e._inputs[e._inputs.indexOf(i)]=a})),a._definition=a._duplicate,a._duplicate=void 0,o._dirty.add(i).add(a),o._updates.add(a),r.set(this._name,a))}if(this._outputs.size)throw new Error;e&&((a=r.get(e))?3===a._type?(this._definition=tn(e),this._duplicate=n,a._duplicates.add(this)):2===a._type?(this._outputs=a._outputs,a._outputs=new Set,this._outputs.forEach((function(e){e._inputs[e._inputs.indexOf(a)]=this}),this),o._dirty.add(a).add(this),r.set(e,this)):(a._duplicate=a._definition,this._duplicate=n,(i=new Kt(3,this._module))._name=e,i._definition=this._definition=a._definition=tn(e),i._outputs=a._outputs,a._outputs=new Set,i._outputs.forEach((function(e){e._inputs[e._inputs.indexOf(a)]=i})),i._duplicates=new Set([this,a]),o._dirty.add(a).add(i),o._updates.add(a).add(i),r.set(e,i)):r.set(e,this)),this._name=e}return o._updates.add(this),o._compute(),this}function rn(e,t=[]){Object.defineProperties(this,{_runtime:{value:e},_scope:{value:new Map},_builtins:{value:new Map([["invalidation",sn],["visibility",ln],...t])},_source:{value:null,writable:!0}})}function on(e){return e._name}Object.defineProperties(Kt.prototype,{_pending:{value:function(){this._observer.pending&&this._observer.pending()},writable:!0,configurable:!0},_fulfilled:{value:function(e){this._observer.fulfilled&&this._observer.fulfilled(e,this._name)},writable:!0,configurable:!0},_rejected:{value:function(e){this._observer.rejected&&this._observer.rejected(e,this._name)},writable:!0,configurable:!0},define:{value:function(e,t,n){switch(arguments.length){case 1:n=e,e=t=null;break;case 2:n=t,"string"==typeof e?t=null:(t=e,e=null)}return nn.call(this,null==e?null:e+"",null==t?[]:Wt.call(t,this._module._resolve,this._module),"function"==typeof n?n:Vt(n))},writable:!0,configurable:!0},delete:{value:function(){return nn.call(this,null,[],Yt)},writable:!0,configurable:!0},import:{value:function(e,t,n){arguments.length<3&&(n=t,t=e);return nn.call(this,t+"",[n._resolve(e+"")],Jt)},writable:!0,configurable:!0}}),Object.defineProperties(rn.prototype,{_copy:{value:function(e,t){e._source=this,t.set(this,e);for(const[i,a]of this._scope){var n=e._scope.get(i);if(!n||1!==n._type)if(a._definition===Jt){var r=a._inputs[0],o=r._module;e.import(r._name,i,t.get(o)||(o._source?o._copy(new rn(e._runtime,e._builtins),t):o))}else e.define(i,a._inputs.map(on),a._definition)}return e},writable:!0,configurable:!0},_resolve:{value:function(e){var t,n=this._scope.get(e);if(!n)if(n=new Kt(2,this),this._builtins.has(e))n.define(e,Vt(this._builtins.get(e)));else if(this._runtime._builtin._scope.has(e))n.import(e,this._runtime._builtin);else{try{t=this._runtime._global(e)}catch(t){return n.define(e,(r=t,function(){throw r}))}void 0===t?this._scope.set(n._name=e,n):n.define(e,Vt(t))}var r;return n},writable:!0,configurable:!0},redefine:{value:function(e){var t=this._scope.get(e);if(!t)throw new Bt(e+" is not defined");if(3===t._type)throw new Bt(e+" is defined more than once");return t.define.apply(t,arguments)},writable:!0,configurable:!0},define:{value:function(){var e=new Kt(1,this);return e.define.apply(e,arguments)},writable:!0,configurable:!0},derive:{value:function(e,t){var n=new rn(this._runtime,this._builtins);return n._source=this,Zt.call(e,(function(e){"object"!=typeof e&&(e={name:e+""}),null==e.alias&&(e.alias=e.name),n.import(e.name,e.alias,t)})),Promise.resolve().then((()=>{const e=new Set([this]);for(const t of e)for(const n of t._scope.values())if(n._definition===Jt){const t=n._inputs[0]._module,r=t._source||t;if(r===this)return void console.warn("circular module definition; ignoring");e.add(r)}this._copy(n,new Map)})),n},writable:!0,configurable:!0},import:{value:function(){var e=new Kt(1,this);return e.import.apply(e,arguments)},writable:!0,configurable:!0},value:{value:async function(e){var t=this._scope.get(e);if(!t)throw new Bt(e+" is not defined");t._observer===Gt&&(t._observer=!0,this._runtime._dirty.add(t));return await this._runtime._compute(),t._promise},writable:!0,configurable:!0},variable:{value:function(e){return new Kt(1,this,e)},writable:!0,configurable:!0},builtin:{value:function(e,t){this._builtins.set(e,t)},writable:!0,configurable:!0}});const an="function"==typeof requestAnimationFrame?requestAnimationFrame:setImmediate;var sn={},ln={};function un(e=new It,t=wn){var n=this.module();if(Object.defineProperties(this,{_dirty:{value:new Set},_updates:{value:new Set},_computing:{value:null,writable:!0},_init:{value:null,writable:!0},_modules:{value:new Map},_variables:{value:new Set},_disposed:{value:!1,writable:!0},_builtin:{value:n},_global:{value:t}}),e)for(var r in e)new Kt(2,n).define(r,[],e[r])}function cn(e){const t=new Set(e._inputs);for(const n of t){if(n===e)return!0;n._inputs.forEach(t.add,t)}return!1}function dn(e){++e._indegree}function fn(e){--e._indegree}function hn(e){return e._promise.catch(e._rejector)}function pn(e){return new Promise((function(t){e._invalidate=t}))}function mn(e,t){let n,r,o="function"==typeof IntersectionObserver&&t._observer&&t._observer._node,i=!o,a=Yt,s=Yt;return o&&(r=new IntersectionObserver((([e])=>(i=e.isIntersecting)&&(n=null,a()))),r.observe(o),e.then((()=>(r.disconnect(),r=null,s())))),function(e){return i?Promise.resolve(e):r?(n||(n=new Promise(((e,t)=>(a=e,s=t)))),n.then((()=>e))):Promise.reject()}}function vn(e){e._invalidate(),e._invalidate=Yt,e._pending();var t=e._value,n=++e._version,r=null,o=e._promise=Promise.all(e._inputs.map(hn)).then((function(o){if(e._version===n){for(var i=0,a=o.length;it._reachable?this._updates.add(t):n