159 строки
6.2 KiB
TypeScript
159 строки
6.2 KiB
TypeScript
///<reference path='refs.ts'/>
|
|
module TDev.RT {
|
|
export module EditorServices {
|
|
export function getTokenAsync(aud: string): Promise {
|
|
if (!Cloud.getAccessToken()) return Promise.as(undefined);
|
|
|
|
var tokens: TDev.StringMap<string>;
|
|
try {
|
|
tokens = JSON.parse(localStorage["touchDevelopTokens"]);
|
|
} catch (e) { tokens = {}; }
|
|
var token = tokens[aud];
|
|
if (token) return Promise.as(token);
|
|
|
|
var url = "https://touchdevelopuserauth.azurewebsites.net/api/sign_token?aud="
|
|
+ encodeURIComponent(aud) + "&access_token=" + Cloud.getAccessToken();
|
|
return Util.httpPostJsonAsync(url, {})
|
|
.then(resp => {
|
|
if (!resp.jwt) Util.oops(resp ? resp.status : "bad")
|
|
return resp.jwt
|
|
})
|
|
.then(token => {
|
|
if (token) {
|
|
tokens[aud] = token;
|
|
localStorage["touchDevelopTokens"] = JSON.stringify(tokens);
|
|
}
|
|
return token;
|
|
}, e => undefined)
|
|
}
|
|
}
|
|
|
|
//? An interface to TouchDevelop editor
|
|
//@ stem("editor") ctx(general,gckey)
|
|
export class Editor
|
|
extends RTValue
|
|
{
|
|
public allAnnotations:AstAnnotation[] = [];
|
|
|
|
constructor(rt:Runtime, headless:boolean)
|
|
{
|
|
super()
|
|
rt.headlessPluginMode = headless;
|
|
rt.editorObj = this;
|
|
}
|
|
|
|
//? Replace standard 'running plugin' message with something else
|
|
public progress(message:string, s:IStackFrame) : void
|
|
{
|
|
ProgressOverlay.setProgress(message)
|
|
}
|
|
|
|
//? Place a message on an AST node
|
|
//@ [category].deflStrings("warning", "info", "error")
|
|
public annotate_ast(id:string, category:string, message:string) : void
|
|
{
|
|
this.allAnnotations.push({ id: id, category: category, message: message })
|
|
}
|
|
|
|
//? The id of the script currently in the editor
|
|
public current_script_id(s:IStackFrame) : string
|
|
{
|
|
return s.rt.runningPluginOn
|
|
}
|
|
|
|
//? Returns the AST of the script currently in the editor
|
|
//@ returns(JsonObject) uiAsync
|
|
public current_script_ast(r:ResumeCtx)
|
|
{
|
|
Bazaar.ast_of(this.current_script_id(r.stackframe), r)
|
|
}
|
|
|
|
//? Signal that the current tutorial step is done.
|
|
public tutorial_step_completed(s:IStackFrame)
|
|
{
|
|
Tutorial.step_completed(s)
|
|
}
|
|
|
|
//? Get (Azure) web site deployment settings.
|
|
//@ returns(JsonObject) async
|
|
public deployment_settings(r:ResumeCtx)
|
|
{
|
|
r.rt.host.deploymentSettingsAsync(r.rt.runningPluginOn)
|
|
.done(ds => r.resumeVal(ds ? JsonObject.wrap(ds) : undefined))
|
|
}
|
|
|
|
//? Authenticates the user for the given app name and returns the token if successful. The identity of the token is contructed with ``{app name} - {user id}``.
|
|
//@ async returns(string) cap(editoronly)
|
|
public user_token(app_name : string, r: ResumeCtx) {
|
|
if (Cloud.anonMode(lf("user token"))) {
|
|
r.resumeVal("");
|
|
return;
|
|
}
|
|
if (!app_name || app_name.length < 4)
|
|
Util.userError(lf("app name must be at least 4 character long"));
|
|
|
|
var userid = Cloud.getUserId();
|
|
var pluginid = lf("{0} - {1}", app_name, userid);
|
|
|
|
if (!r.rt.host.askSourceAccessAsync("a user token for " + pluginid, "an authentication token for the `" + pluginid + "` application. The token allows this script to authenticate you in their services. The script does not have access to any other personal information.", true)) {
|
|
r.resumeVal("");
|
|
return;
|
|
}
|
|
|
|
EditorServices
|
|
.getTokenAsync(pluginid)
|
|
.done(token => r.resumeVal(token));
|
|
}
|
|
|
|
//? Uploads a payload to a temporary blob and retreives the url. While the URL will remain unchanged, the data will eventually be wiped out.
|
|
//@ async returns(string) cap(editoronly)
|
|
public upload_json(payload: JsonBuilder, r: ResumeCtx) { // string
|
|
if (Cloud.anonMode(lf("upload plugin data"))) {
|
|
r.resumeVal("");
|
|
return;
|
|
}
|
|
|
|
var pluginid = r.rt.currentScriptId || "__unpublished__";
|
|
EditorServices
|
|
.getTokenAsync("TouchDevelop Bin")
|
|
.then(token => {
|
|
if (!token) {
|
|
r.resumeVal("");
|
|
return;
|
|
}
|
|
return Util.httpPostRealJsonAsync("https://touchdevelopbin.azurewebsites.net/api/upload",
|
|
{ token: token, pluginid: pluginid, payload: payload.value() });
|
|
}).done(resp => {
|
|
if (resp) r.resumeVal(resp["url"] || "");
|
|
else r.resumeVal("");
|
|
}, e => { r.resumeVal(""); })
|
|
}
|
|
|
|
//? Compiles and packages the current script.
|
|
//@ async returns(JsonObject) cap(editoronly) dbgOnly
|
|
public package_current_script(options : JsonObject, r : ResumeCtx) {
|
|
HTML.showProgressNotification(lf("packaging script..."), true);
|
|
var id = this.current_script_id(r.stackframe);
|
|
r.rt.host.packageScriptAsync(id, options.value())
|
|
.done(
|
|
instr => r.resumeVal(JsonObject.wrap(instr)),
|
|
err => r.resumeVal(JsonObject.wrap({ error: err.message || "an error occured" }))
|
|
);
|
|
}
|
|
}
|
|
|
|
export interface AstAnnotationOp {
|
|
opid: string;
|
|
header: string;
|
|
description: string;
|
|
}
|
|
|
|
export interface AstAnnotation {
|
|
id:string; // of the node
|
|
category:string;
|
|
message:string;
|
|
ops?:AstAnnotationOp[];
|
|
pluginRef?:string;
|
|
}
|
|
}
|