Page Menu
Home
Sealhub
Search
Configure Global Search
Log In
Files
F969442
index.ts
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
5 KB
Referenced Files
None
Subscribers
None
index.ts
View Options
import
EventEmitter
from
"events"
;
import
{
Readable
}
from
"stream"
;
import
pipeInto
from
"./pipe-into"
;
import
{
Stringifiable
,
stringify
}
from
"./stringify"
;
import
{
HTMLTag
}
from
"./html"
;
export
{
default
as
streamToString
}
from
"./tostring"
;
export
{
TempstreamJSX
}
from
"./jsx"
;
/* eslint-disable */
declare
global
{
namespace
JSX
{
type
HtmlAttribute
=
string
|
boolean
;
type
HtmlElement
=
HTMLTag
;
interface
IntrinsicElements
extends
IntrinsicElementMap
{}
interface
InstrictPropsInterface
{
[
k
:
string
]
:
HtmlAttribute
|
Promise
<
HtmlAttribute
>
;
}
type
IntrinsicElementMap
=
{
[
K
in
HtmlElement
]
:
InstrictPropsInterface
&
{
children
?:
HtmlElement
|
HtmlElement
[];
};
};
type
Element
=
Readable
;
}
}
/* eslint-enable */
export
type
MaybePromise
<
T
>
=
T
|
Promise
<
T
>
;
export
type
MaybeArray
<
T
>
=
T
|
Array
<
T
>
;
export
type
MaybePromiseMaybeArray
<
T
>
=
|
T
|
T
[]
|
(
T
|
Promise
<
T
>
)[]
|
Promise
<
T
>
|
Promise
<
Promise
<
T
>
|
T
[]
>
|
Promise
<
T
[]
>
|
Promise
<
T
>
[];
export
type
FlatTemplatable
=
Stringifiable
;
export
type
Templatable
=
MaybePromise
<
MaybeArray
<
MaybePromise
<
FlatTemplatable
>>
>
;
const
ErrorSymbol
=
Symbol
(
"ErrorSymbol"
);
let
unhandledRejectionHandlerSetup
=
false
;
function
setupUnhandledRejection
()
{
if
(
unhandledRejectionHandlerSetup
)
{
return
;
}
console
.
log
(
"Setting up unhandled rejection listener"
);
process
.
on
(
"unhandledRejection"
,
(
error
:
Error
,
promise
:
unknown
)
=>
{
console
.
error
(
"UNHANDLED REJECTION:"
);
console
.
error
(
error
);
console
.
error
(
"FOR PROMISE:"
);
console
.
error
(
promise
);
console
.
error
(
`!! You're using tempstream, which encaurages passing promises to template
strings. This is a delicate operation! Make sure you're not doing this:
\`\`\`
const data_promise = fetchData(); // returns a Promise
await sleep(200); // <== the process sleeps, while the above Promise rejects
return tempstream\`some data: \${data_promise.then(data=>data.name)}\` // <== tempstream automatically sets up error handlers, but it's too late!
\`\`\`
The problem with the above example is that the \`await sleep(200)\` allows the
data_promise to fail before tempstream manages to add .catch handlers to
it. Either add the error handlers yourself, or don't do any \`await\`s inbetween
promises runing in the background and returning the tempstream.
`
);
process
.
exit
(
1
);
});
unhandledRejectionHandlerSetup
=
true
;
}
setupUnhandledRejection
();
export
type
TemplateGenError
=
{
ErrorSymbol
:
symbol
;
error
:
Error
};
async
function
*
templateGen
(
strings
:
TemplateStringsArray
,
...
params
:
Templatable
[]
)
{
for
(
const
string
of
strings
)
{
yield
string
;
const
param
=
params
.
shift
();
try
{
yield
param
;
}
catch
(
error
:
unknown
)
{
yield
{
ErrorSymbol
,
error
};
}
}
yield
null
;
}
export
class
TempStream
extends
Readable
{
is_piping_substream
=
false
;
is_handling_array
=
false
;
is_finished
=
false
;
has_errors
=
false
;
id
=
Math
.
random
();
emitter
=
new
EventEmitter
();
constructor
(
public
generator
:
ReturnType
<
typeof
templateGen
>
)
{
super
();
}
async
_read
()
{
if
(
this
.
is_piping_substream
||
this
.
is_handling_array
)
{
return
;
}
try
{
const
result
=
await
this
.
generator
.
next
();
const
value
=
result
?
.
value
;
if
(
typeof
value
===
"object"
&&
(
value
as
TemplateGenError
)
?
.
ErrorSymbol
===
ErrorSymbol
)
{
this
.
finishStream
(
"error"
,
(
value
as
TemplateGenError
)
?
.
error
);
}
await
this
.
handleResult
(
result
,
(
data
)
=>
{
this
.
push
(
data
);
},
()
=>
this
.
finishStream
(
"success"
)
);
}
catch
(
e
)
{
this
.
finishStream
(
"error"
,
e
);
}
}
waitUntilFinished
()
{
return
new
Promise
((
resolve
)
=>
{
if
(
this
.
is_finished
)
{
resolve
(
this
);
}
else
{
this
.
emitter
.
on
(
"finished"
,
()
=>
resolve
(
this
));
}
});
}
finishStream
(
status
:
"error"
|
"success"
,
error
?:
unknown
)
{
if
(
status
===
"error"
)
{
this
.
emit
(
"error"
,
error
);
this
.
emitter
.
emit
(
"promise-error"
,
error
);
this
.
has_errors
=
true
;
}
else
{
this
.
emitter
.
emit
(
"success"
);
}
this
.
emitter
.
emit
(
"success"
);
this
.
emitter
.
emit
(
"finished"
);
this
.
is_finished
=
true
;
this
.
push
(
null
);
// end the stream
}
async
handleSingleResult
(
subvalue
:
unknown
,
push
:
(
data
:
any
)
=>
void
)
{
if
(
subvalue
instanceof
Readable
)
{
this
.
is_piping_substream
=
true
;
await
pipeInto
(
subvalue
,
push
)
.
then
(()
=>
{
this
.
is_piping_substream
=
false
;
void
this
.
_read
();
})
.
catch
((
error
)
=>
{
this
.
finishStream
(
"error"
,
error
);
});
}
else
{
push
(
await
stringify
(
subvalue
as
Stringifiable
));
}
}
async
serializePluralResult
(
value
:
unknown
,
push
:
(
data
:
any
)
=>
void
)
{
value
=
await
value
;
if
(
Array
.
isArray
(
value
))
{
this
.
is_handling_array
=
true
;
for
(
const
[
index
,
subvalue
]
of
Object
.
entries
(
value
))
{
// eslint-disable-next-line no-await-in-loop
await
this
.
serializePluralResult
(
subvalue
,
push
);
if
(
parseInt
(
index
)
<
value
.
length
-
1
)
push
(
"\n"
);
}
this
.
is_handling_array
=
false
;
void
this
.
_read
();
}
else
{
await
this
.
handleSingleResult
(
value
,
push
);
}
}
async
handleResult
(
result
:
IteratorResult
<
unknown
>
,
push
:
(
data
:
any
)
=>
void
,
end
:
()
=>
void
)
{
if
(
result
.
done
)
{
push
(
null
);
end
();
}
const
value
:
unknown
=
result
.
value
;
await
this
.
serializePluralResult
(
await
value
,
push
);
}
push
(
data
:
unknown
)
:
boolean
{
super
.
push
(
data
);
return
true
;
}
}
export
function
tempstream
(
strings
:
TemplateStringsArray
,
...
params
:
Templatable
[]
)
:
Readable
{
params
.
forEach
((
param
)
=>
{
if
(
param
instanceof
Promise
)
{
param
.
catch
((
e
)
=>
{
console
.
log
(
"Error caught within tempstream main function"
);
console
.
error
(
e
);
});
}
});
return
new
TempStream
(
templateGen
(
strings
,
...
params
));
}
File Metadata
Details
Attached
Mime Type
text/x-java
Expires
Sat, Nov 23, 02:31 (1 d, 7 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
547793
Default Alt Text
index.ts (5 KB)
Attached To
Mode
rSTREAM tempstream
Attached
Detach File
Event Timeline
Log In to Comment