Add SQLite-backed AuthSessionStore

Every operation the SlateDB store answers with a full keyspace scan becomes
an indexed query here: listing a user's sessions joins one row per session
via the partial unique index instead of scanning every token ever issued
and grouping by chain, and revoking one is a single DELETE that cascades.

Rotation is the structural win. Claiming the presented token is one
`UPDATE ... WHERE used_at_ms IS NULL ... RETURNING`, and it is the
transaction's first statement, so SQLite takes the write lock before
anything is read. A concurrent caller blocks on that lock and then sees the
token already spent, which is exactly the replay signal -- so the store
needs no `KeyedMutex` to serialise rotation, and the guarantee survives more
than one server process.

Expiry is checked ahead of reuse on the cold path, preserving the ordering
callers depend on: only replaying a still-live token revokes its chain.

Drops the ordering CHECKs between a session's timestamps and its tokens'.
Rotation stamps `now` from the process clock against rows written by an
earlier request, so an NTP step backwards would have turned a harmless clock
anomaly into refresh failing outright for every affected session.

The store is not wired into the server yet.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-07-25 23:42:14 -04:00
parent c69a47c4e6
commit 701708b32d
No known key found for this signature in database
371 changed files with 22025 additions and 9 deletions

View file

@ -0,0 +1,801 @@
//! SQLite-backed storage for CLI auth sessions and their refresh tokens.
//!
//! A session is a rotation chain. The chain owns the identity and profile;
//! each token in it owns only its own lifetime. Splitting them that way is
//! what makes every operation here an indexed query rather than a scan over
//! every token ever issued.
use chrono::{DateTime, Utc};
use fabro_types::IdpIdentity;
use sqlx::sqlite::SqliteRow;
use sqlx::{Row as _, SqlitePool};
use uuid::Uuid;
use crate::{Error, Result};
/// A CLI auth session: one rotation chain, owned by one identity.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AuthSessionRecord {
pub id: Uuid,
pub identity: IdpIdentity,
pub login: String,
pub name: String,
pub email: String,
pub avatar_url: String,
pub user_agent: String,
pub created_at: DateTime<Utc>,
pub last_used_at: DateTime<Utc>,
}
/// One refresh token within a session. `used_at` is set when the token is
/// rotated away; the row is kept until expiry so a replay stays recognisable.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RefreshToken {
pub token_hash: [u8; 32],
pub session_id: Uuid,
pub issued_at: DateTime<Utc>,
pub expires_at: DateTime<Utc>,
pub used_at: Option<DateTime<Utc>>,
}
/// A session with a spendable token, as returned by the session listing.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ActiveCliSession {
pub session: AuthSessionRecord,
/// Expiry of the session's live token.
pub expires_at: DateTime<Utc>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RotateOutcome {
/// The presented token was spent and its successor issued.
Rotated(AuthSessionRecord),
/// The presented token had already been rotated away — a replay.
Reused(AuthSessionRecord),
Expired,
NotFound,
}
pub struct AuthSessionStore {
pool: SqlitePool,
}
impl std::fmt::Debug for AuthSessionStore {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("AuthSessionStore").finish_non_exhaustive()
}
}
const SELECT_SESSION_BY_TOKEN_SQL: &str = r"
SELECT s.id, s.identity_issuer, s.identity_subject, s.login, s.name, s.email,
s.avatar_url, s.user_agent, s.created_at_ms, s.last_used_at_ms
FROM auth_sessions s
JOIN refresh_tokens t ON t.session_id = s.id
WHERE t.token_hash = ?
";
const SELECT_ACTIVE_SESSIONS_SQL: &str = r"
SELECT s.id, s.identity_issuer, s.identity_subject, s.login, s.name, s.email,
s.avatar_url, s.user_agent, s.created_at_ms, s.last_used_at_ms,
t.expires_at_ms
FROM auth_sessions s
JOIN refresh_tokens t ON t.session_id = s.id AND t.used_at_ms IS NULL
WHERE s.identity_issuer = ? AND s.identity_subject = ? AND t.expires_at_ms > ?
ORDER BY s.last_used_at_ms DESC
";
const SELECT_SESSION_BY_ID_SQL: &str = r"
SELECT s.id, s.identity_issuer, s.identity_subject, s.login, s.name, s.email,
s.avatar_url, s.user_agent, s.created_at_ms, s.last_used_at_ms
FROM auth_sessions s
WHERE s.id = ?
";
impl AuthSessionStore {
#[must_use]
pub fn new(pool: SqlitePool) -> Self {
Self { pool }
}
/// Open a new session with its first refresh token.
pub async fn create_session(
&self,
session: &AuthSessionRecord,
token: &RefreshToken,
) -> Result<()> {
let mut tx = self.pool.begin().await?;
sqlx::query(
r"
INSERT INTO auth_sessions (
id, identity_issuer, identity_subject, login, name, email, avatar_url,
user_agent, created_at_ms, last_used_at_ms
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
",
)
.bind(session.id.to_string())
.bind(session.identity.issuer())
.bind(session.identity.subject())
.bind(&session.login)
.bind(&session.name)
.bind(&session.email)
.bind(&session.avatar_url)
.bind(&session.user_agent)
.bind(session.created_at.timestamp_millis())
.bind(session.last_used_at.timestamp_millis())
.execute(&mut *tx)
.await?;
insert_token(&mut tx, token).await?;
tx.commit().await?;
Ok(())
}
/// Look up the session a token belongs to, spent or not.
pub async fn find_session_by_token_hash(
&self,
token_hash: &[u8; 32],
) -> Result<Option<AuthSessionRecord>> {
sqlx::query(SELECT_SESSION_BY_TOKEN_SQL)
.bind(token_hash.as_slice())
.fetch_optional(&self.pool)
.await?
.as_ref()
.map(session_from_row)
.transpose()
}
/// Sessions belonging to `identity` that still hold a spendable token.
///
/// The partial unique index guarantees at most one live token per
/// session, so this joins one row per session rather than grouping
/// candidates.
pub async fn active_cli_sessions(
&self,
identity: &IdpIdentity,
now: DateTime<Utc>,
) -> Result<Vec<ActiveCliSession>> {
sqlx::query(SELECT_ACTIVE_SESSIONS_SQL)
.bind(identity.issuer())
.bind(identity.subject())
.bind(now.timestamp_millis())
.fetch_all(&self.pool)
.await?
.into_iter()
.map(|row| {
let expires_at = timestamp_from_row(&row, "expires_at_ms")?;
Ok(ActiveCliSession {
session: session_from_row(&row)?,
expires_at,
})
})
.collect()
}
/// Spend `presented_hash` and issue `new_token_hash` in its place.
///
/// The claiming UPDATE is the transaction's first statement, so SQLite
/// takes the write lock before anything is read. A concurrent caller
/// blocks on it, then observes `used_at_ms` already set and gets
/// [`RotateOutcome::Reused`] — the replay signal — with no application
/// mutex involved.
pub async fn rotate(
&self,
presented_hash: &[u8; 32],
new_token_hash: &[u8; 32],
new_expires_at: DateTime<Utc>,
user_agent: &str,
now: DateTime<Utc>,
) -> Result<RotateOutcome> {
let now_ms = now.timestamp_millis();
let mut tx = self.pool.begin().await?;
let claimed: Option<String> = sqlx::query_scalar(
r"
UPDATE refresh_tokens SET used_at_ms = ?
WHERE token_hash = ? AND used_at_ms IS NULL AND expires_at_ms > ?
RETURNING session_id
",
)
.bind(now_ms)
.bind(presented_hash.as_slice())
.bind(now_ms)
.fetch_optional(&mut *tx)
.await?;
let Some(session_id) = claimed else {
// Cold path: the claim failed, so read once more to say why.
let existing: Option<(Option<i64>, i64)> = sqlx::query_as(
"SELECT used_at_ms, expires_at_ms FROM refresh_tokens WHERE token_hash = ?",
)
.bind(presented_hash.as_slice())
.fetch_optional(&mut *tx)
.await?;
// Expiry is checked before reuse so an expired token reports as
// expired even if it had already been rotated away, matching the
// ordering callers rely on: only a live replay revokes the chain.
let outcome = match existing {
None => RotateOutcome::NotFound,
Some((used_at_ms, expires_at_ms)) => {
if expires_at_ms <= now_ms {
RotateOutcome::Expired
} else if used_at_ms.is_some() {
let session = load_session(&mut tx, presented_hash).await?;
session.map_or(RotateOutcome::NotFound, RotateOutcome::Reused)
} else {
// Unreachable: a live, unexpired token would have been
// claimed by the UPDATE above, in this transaction.
RotateOutcome::NotFound
}
}
};
tx.commit().await?;
return Ok(outcome);
};
let session_id = parse_uuid(&session_id)?;
insert_token(&mut tx, &RefreshToken {
token_hash: *new_token_hash,
session_id,
issued_at: now,
expires_at: new_expires_at,
used_at: None,
})
.await?;
sqlx::query("UPDATE auth_sessions SET last_used_at_ms = ?, user_agent = ? WHERE id = ?")
.bind(now_ms)
.bind(user_agent)
.bind(session_id.to_string())
.execute(&mut *tx)
.await?;
let row = sqlx::query(SELECT_SESSION_BY_ID_SQL)
.bind(session_id.to_string())
.fetch_one(&mut *tx)
.await?;
let session = session_from_row(&row)?;
tx.commit().await?;
Ok(RotateOutcome::Rotated(session))
}
/// Revoke a session outright. Its tokens go with it via `ON DELETE
/// CASCADE`.
pub async fn delete_session(&self, session_id: Uuid) -> Result<()> {
sqlx::query("DELETE FROM auth_sessions WHERE id = ?")
.bind(session_id.to_string())
.execute(&self.pool)
.await?;
Ok(())
}
/// Revoke a session on behalf of its owner, but only while it is still
/// usable. Returns the number of sessions deleted (0 or 1), so a caller
/// can distinguish "revoked" from "no such live session".
pub async fn delete_active_session_for_identity(
&self,
identity: &IdpIdentity,
session_id: Uuid,
now: DateTime<Utc>,
) -> Result<u64> {
let deleted = sqlx::query(
r"
DELETE FROM auth_sessions
WHERE id = ? AND identity_issuer = ? AND identity_subject = ?
AND EXISTS (
SELECT 1 FROM refresh_tokens t
WHERE t.session_id = auth_sessions.id
AND t.used_at_ms IS NULL
AND t.expires_at_ms > ?
)
",
)
.bind(session_id.to_string())
.bind(identity.issuer())
.bind(identity.subject())
.bind(now.timestamp_millis())
.execute(&self.pool)
.await?
.rows_affected();
Ok(deleted)
}
/// Drop expired tokens, then any session left without one. Returns the
/// number of tokens removed.
pub async fn gc_expired(&self, cutoff: DateTime<Utc>) -> Result<u64> {
let mut tx = self.pool.begin().await?;
let tokens = sqlx::query("DELETE FROM refresh_tokens WHERE expires_at_ms <= ?")
.bind(cutoff.timestamp_millis())
.execute(&mut *tx)
.await?
.rows_affected();
sqlx::query(
r"
DELETE FROM auth_sessions
WHERE NOT EXISTS (SELECT 1 FROM refresh_tokens t WHERE t.session_id = auth_sessions.id)
",
)
.execute(&mut *tx)
.await?;
tx.commit().await?;
Ok(tokens)
}
}
async fn insert_token(
tx: &mut sqlx::Transaction<'_, sqlx::Sqlite>,
token: &RefreshToken,
) -> Result<()> {
sqlx::query(
r"
INSERT INTO refresh_tokens (token_hash, session_id, issued_at_ms, expires_at_ms, used_at_ms)
VALUES (?, ?, ?, ?, ?)
",
)
.bind(token.token_hash.as_slice())
.bind(token.session_id.to_string())
.bind(token.issued_at.timestamp_millis())
.bind(token.expires_at.timestamp_millis())
.bind(token.used_at.map(|used_at| used_at.timestamp_millis()))
.execute(&mut **tx)
.await?;
Ok(())
}
async fn load_session(
tx: &mut sqlx::Transaction<'_, sqlx::Sqlite>,
token_hash: &[u8; 32],
) -> Result<Option<AuthSessionRecord>> {
sqlx::query(SELECT_SESSION_BY_TOKEN_SQL)
.bind(token_hash.as_slice())
.fetch_optional(&mut **tx)
.await?
.as_ref()
.map(session_from_row)
.transpose()
}
fn session_from_row(row: &SqliteRow) -> Result<AuthSessionRecord> {
let identity = IdpIdentity::new(
row.try_get::<String, _>("identity_issuer")?,
row.try_get::<String, _>("identity_subject")?,
)
.map_err(|err| {
Error::Other(format!(
"stored auth session has an invalid identity: {err}"
))
})?;
Ok(AuthSessionRecord {
id: parse_uuid(&row.try_get::<String, _>("id")?)?,
identity,
login: row.try_get("login")?,
name: row.try_get("name")?,
email: row.try_get("email")?,
avatar_url: row.try_get("avatar_url")?,
user_agent: row.try_get("user_agent")?,
created_at: timestamp_from_row(row, "created_at_ms")?,
last_used_at: timestamp_from_row(row, "last_used_at_ms")?,
})
}
fn timestamp_from_row(row: &SqliteRow, column: &str) -> Result<DateTime<Utc>> {
let millis: i64 = row.try_get(column)?;
DateTime::from_timestamp_millis(millis)
.ok_or_else(|| Error::Other(format!("stored auth session has an invalid {column}")))
}
fn parse_uuid(value: &str) -> Result<Uuid> {
Uuid::parse_str(value)
.map_err(|err| Error::Other(format!("stored auth session has an invalid id: {err}")))
}
#[cfg(test)]
mod tests {
use std::sync::Arc;
use chrono::{Duration, Utc};
use fabro_types::IdpIdentity;
use tokio::task::JoinSet;
use uuid::Uuid;
use super::{AuthSessionRecord, AuthSessionStore, RefreshToken, RotateOutcome};
use crate::test_util::sqlite_auth_session_store;
fn identity(subject: &str) -> IdpIdentity {
IdpIdentity::new("https://github.com", subject).unwrap()
}
fn session(id: Uuid, subject: &str) -> AuthSessionRecord {
let now = Utc::now();
AuthSessionRecord {
id,
identity: identity(subject),
login: "octocat".to_string(),
name: "The Octocat".to_string(),
email: "octocat@example.com".to_string(),
avatar_url: "https://example.com/octocat.png".to_string(),
user_agent: "fabro-cli/0.3".to_string(),
created_at: now,
last_used_at: now,
}
}
/// Tokens are issued an hour back so that a fixture with a negative
/// `expires_in` is still a coherent row: issued in the past, expired since.
fn token(hash: [u8; 32], session_id: Uuid, expires_in: Duration) -> RefreshToken {
let now = Utc::now();
RefreshToken {
token_hash: hash,
session_id,
issued_at: now - Duration::hours(1),
expires_at: now + expires_in,
used_at: None,
}
}
async fn open_session(
store: &AuthSessionStore,
subject: &str,
hash: [u8; 32],
expires_in: Duration,
) -> Uuid {
let id = Uuid::new_v4();
store
.create_session(&session(id, subject), &token(hash, id, expires_in))
.await
.unwrap();
id
}
#[tokio::test]
async fn create_session_round_trips_through_its_token() {
let (_dir, store) = sqlite_auth_session_store().await;
let id = open_session(&store, "12345", [1_u8; 32], Duration::days(30)).await;
let found = store
.find_session_by_token_hash(&[1_u8; 32])
.await
.unwrap()
.expect("session should be found by its token");
assert_eq!(found.id, id);
assert_eq!(found.identity, identity("12345"));
assert_eq!(found.login, "octocat");
assert_eq!(found.avatar_url, "https://example.com/octocat.png");
assert!(
store
.find_session_by_token_hash(&[9_u8; 32])
.await
.unwrap()
.is_none()
);
}
#[tokio::test]
async fn rotate_spends_the_presented_token_and_issues_its_successor() {
let (_dir, store) = sqlite_auth_session_store().await;
let id = open_session(&store, "12345", [1_u8; 32], Duration::days(30)).await;
let now = Utc::now();
let outcome = store
.rotate(
&[1_u8; 32],
&[2_u8; 32],
now + Duration::days(30),
"fabro-cli/0.4",
now,
)
.await
.unwrap();
let RotateOutcome::Rotated(rotated) = outcome else {
panic!("expected rotation, got {outcome:?}");
};
assert_eq!(rotated.id, id);
// The rotation refreshes the session's user agent and last-used time,
// while created_at stays the true start of the chain.
assert_eq!(rotated.user_agent, "fabro-cli/0.4");
assert_eq!(
rotated.last_used_at.timestamp_millis(),
now.timestamp_millis()
);
assert!(rotated.created_at < rotated.last_used_at);
// Both tokens still resolve to the session; only the new one is live.
assert!(
store
.find_session_by_token_hash(&[1_u8; 32])
.await
.unwrap()
.is_some()
);
let active = store
.active_cli_sessions(&identity("12345"), now)
.await
.unwrap();
assert_eq!(active.len(), 1);
assert_eq!(active[0].session.id, id);
}
#[tokio::test]
async fn rotate_reports_reuse_when_a_spent_token_is_replayed() {
let (_dir, store) = sqlite_auth_session_store().await;
let id = open_session(&store, "12345", [1_u8; 32], Duration::days(30)).await;
let now = Utc::now();
store
.rotate(
&[1_u8; 32],
&[2_u8; 32],
now + Duration::days(30),
"ua",
now,
)
.await
.unwrap();
let replay = store
.rotate(
&[1_u8; 32],
&[3_u8; 32],
now + Duration::days(30),
"ua",
now,
)
.await
.unwrap();
let RotateOutcome::Reused(session) = replay else {
panic!("expected reuse, got {replay:?}");
};
assert_eq!(session.id, id);
}
#[tokio::test]
async fn rotate_reports_expiry_before_reuse() {
let (_dir, store) = sqlite_auth_session_store().await;
let now = Utc::now();
open_session(&store, "12345", [1_u8; 32], Duration::seconds(30)).await;
// An unknown token is simply absent.
assert_eq!(
store
.rotate(
&[9_u8; 32],
&[8_u8; 32],
now + Duration::days(30),
"ua",
now
)
.await
.unwrap(),
RotateOutcome::NotFound
);
// Live but past its expiry.
let later = now + Duration::seconds(60);
assert_eq!(
store
.rotate(
&[1_u8; 32],
&[2_u8; 32],
later + Duration::days(30),
"ua",
later
)
.await
.unwrap(),
RotateOutcome::Expired
);
// Spend it while still valid, then let it expire: expiry wins over
// reuse, so a stale retry does not read as a live replay.
store
.rotate(
&[1_u8; 32],
&[2_u8; 32],
now + Duration::seconds(30),
"ua",
now,
)
.await
.unwrap();
assert_eq!(
store
.rotate(
&[1_u8; 32],
&[4_u8; 32],
later + Duration::days(30),
"ua",
later
)
.await
.unwrap(),
RotateOutcome::Expired
);
}
#[tokio::test]
async fn active_cli_sessions_lists_only_live_sessions_owned_by_the_identity() {
let (_dir, store) = sqlite_auth_session_store().await;
let now = Utc::now();
let live = open_session(&store, "12345", [1_u8; 32], Duration::days(30)).await;
let expired = open_session(&store, "12345", [2_u8; 32], Duration::seconds(-1)).await;
let other = open_session(&store, "67890", [3_u8; 32], Duration::days(30)).await;
let active = store
.active_cli_sessions(&identity("12345"), now)
.await
.unwrap();
let ids: Vec<Uuid> = active.iter().map(|entry| entry.session.id).collect();
assert_eq!(ids, vec![live], "expired={expired}, other-identity={other}");
assert!(active[0].expires_at > now);
// Once the successor token expires in turn, the session drops off the
// list: the spent predecessor does not keep it alive.
store
.rotate(
&[1_u8; 32],
&[4_u8; 32],
now + Duration::seconds(30),
"ua",
now,
)
.await
.unwrap();
assert!(
store
.active_cli_sessions(&identity("12345"), now + Duration::seconds(60))
.await
.unwrap()
.is_empty()
);
}
#[tokio::test]
async fn delete_session_removes_its_tokens() {
let (_dir, store) = sqlite_auth_session_store().await;
let now = Utc::now();
let id = open_session(&store, "12345", [1_u8; 32], Duration::days(30)).await;
store
.rotate(
&[1_u8; 32],
&[2_u8; 32],
now + Duration::days(30),
"ua",
now,
)
.await
.unwrap();
store.delete_session(id).await.unwrap();
for hash in [[1_u8; 32], [2_u8; 32]] {
assert!(
store
.find_session_by_token_hash(&hash)
.await
.unwrap()
.is_none(),
"cascade should remove every token in the chain"
);
}
}
#[tokio::test]
async fn delete_active_session_for_identity_requires_a_live_owned_session() {
let (_dir, store) = sqlite_auth_session_store().await;
let now = Utc::now();
let owned = open_session(&store, "12345", [1_u8; 32], Duration::days(30)).await;
let expired = open_session(&store, "12345", [2_u8; 32], Duration::seconds(-1)).await;
// Another identity cannot revoke it.
assert_eq!(
store
.delete_active_session_for_identity(&identity("67890"), owned, now)
.await
.unwrap(),
0
);
// Neither can the owner, once nothing in it is spendable.
assert_eq!(
store
.delete_active_session_for_identity(&identity("12345"), expired, now)
.await
.unwrap(),
0
);
// An unknown session is a no-op rather than an error.
assert_eq!(
store
.delete_active_session_for_identity(&identity("12345"), Uuid::new_v4(), now)
.await
.unwrap(),
0
);
assert_eq!(
store
.delete_active_session_for_identity(&identity("12345"), owned, now)
.await
.unwrap(),
1
);
assert!(
store
.find_session_by_token_hash(&[1_u8; 32])
.await
.unwrap()
.is_none()
);
assert!(
store
.find_session_by_token_hash(&[2_u8; 32])
.await
.unwrap()
.is_some(),
"revoking one session must not touch another"
);
}
#[tokio::test]
async fn gc_expired_drops_expired_tokens_and_the_sessions_left_empty() {
let (_dir, store) = sqlite_auth_session_store().await;
let now = Utc::now();
let live = open_session(&store, "12345", [1_u8; 32], Duration::days(30)).await;
open_session(&store, "12345", [2_u8; 32], Duration::seconds(-1)).await;
assert_eq!(store.gc_expired(now).await.unwrap(), 1);
assert!(
store
.find_session_by_token_hash(&[2_u8; 32])
.await
.unwrap()
.is_none()
);
assert_eq!(
store
.find_session_by_token_hash(&[1_u8; 32])
.await
.unwrap()
.map(|session| session.id),
Some(live)
);
// Idempotent: a second sweep finds nothing left to remove.
assert_eq!(store.gc_expired(now).await.unwrap(), 0);
}
#[tokio::test]
async fn concurrent_rotation_lets_exactly_one_caller_win() {
let (_dir, store) = sqlite_auth_session_store().await;
let store = Arc::new(store);
let now = Utc::now();
open_session(&store, "12345", [0_u8; 32], Duration::days(30)).await;
let mut tasks = JoinSet::new();
for index in 1..=8_u8 {
let store = Arc::clone(&store);
tasks.spawn(async move {
store
.rotate(
&[0_u8; 32],
&[index; 32],
now + Duration::days(30),
"ua",
now,
)
.await
.unwrap()
});
}
let mut rotated = 0;
let mut reused = 0;
while let Some(outcome) = tasks.join_next().await {
match outcome.unwrap() {
RotateOutcome::Rotated(_) => rotated += 1,
RotateOutcome::Reused(_) => reused += 1,
other => panic!("unexpected outcome {other:?}"),
}
}
// SQLite's write lock serialises the claiming UPDATE, so the losers
// see a spent token rather than racing past it.
assert_eq!(rotated, 1);
assert_eq!(reused, 7);
}
}

View file

@ -1,6 +1,7 @@
use chrono::{DateTime, Utc};
mod artifact_store;
pub mod auth_session_store;
mod error;
mod keyed_mutex;
mod keys;
@ -18,6 +19,9 @@ pub use artifact_store::{
ArtifactKey, ArtifactStore, NodeArtifact, StageArtifactEntry, retry_storage_segment,
stage_storage_segment,
};
// `RefreshToken` and the rotation outcome stay module-qualified while the
// SlateDB-backed store below still exports types under those names.
pub use auth_session_store::{ActiveCliSession, AuthSessionRecord, AuthSessionStore};
pub use error::{Error, Result};
pub use fabro_types::{
EventEnvelope, PendingInterviewRecord, Run, RunBlobId, RunProjection, StageId, StageProjection,

View file

@ -1,4 +1,14 @@
use crate::RunSummaryStore;
use crate::auth_session_store::AuthSessionStore;
pub(crate) async fn sqlite_auth_session_store() -> (tempfile::TempDir, AuthSessionStore) {
let directory = tempfile::tempdir().unwrap();
let database = fabro_db::Database::connect(directory.path().join("fabro.sqlite3"))
.await
.unwrap();
database.migrate().await.unwrap();
(directory, AuthSessionStore::new(database.clone_pool()))
}
pub(crate) async fn sqlite_summary_store() -> (tempfile::TempDir, RunSummaryStore) {
let directory = tempfile::tempdir().unwrap();

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
import{S as a}from"./chunk-c8zhk10v.js";import"./chunk-xg9nsz1a.js";import"./chunk-gf0502ds.js";export{a as default};

View file

@ -0,0 +1 @@
import{d as a}from"./chunk-5q0vf5kd.js";import"./chunk-z1p7fbkb.js";import"./chunk-amk943wr.js";import"./chunk-972wx742.js";import"./chunk-ept66kdn.js";import"./chunk-1ehq66yp.js";import"./chunk-xg9nsz1a.js";import"./chunk-z868q2s0.js";import"./chunk-gf0502ds.js";export{a as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
import{e}from"./chunk-7zy2rxws.js";import"./chunk-gf0502ds.js";var n=Object.freeze(JSON.parse('{"displayName":"Nextflow","name":"nextflow","patterns":[{"include":"#nextflow"}],"repository":{"enum-def":{"begin":"^\\\\s*(enum)\\\\s+(\\\\w+)\\\\s*\\\\{","beginCaptures":{"1":{"name":"keyword.nextflow"},"2":{"name":"storage.type.groovy"}},"end":"}","patterns":[{"include":"source.nextflow-groovy#groovy"},{"include":"#enum-values"}]},"enum-values":{"patterns":[{"begin":"(?<=;|^)\\\\s*\\\\b([0-9A-Z_]+)(?=\\\\s*(?:[(,}]|$))","beginCaptures":{"1":{"name":"constant.enum.name.groovy"}},"end":",|(?=})|^(?!\\\\s*\\\\w+\\\\s*(?:,|$))","patterns":[{"begin":"\\\\(","end":"\\\\)","name":"meta.enum.value.groovy","patterns":[{"match":",","name":"punctuation.definition.seperator.parameter.groovy"},{"include":"#groovy-code"}]}]}]},"function-body":{"patterns":[{"match":"\\\\s"},{"begin":"(?=[<\\\\w][^(]*\\\\s+[$<\\\\w]+\\\\s*\\\\()","end":"(?=[$\\\\w]+\\\\s*\\\\()","name":"meta.method.return-type.java","patterns":[{"include":"source.nextflow-groovy#types"}]},{"begin":"([$\\\\w]+)\\\\s*\\\\(","beginCaptures":{"1":{"name":"entity.name.function.nextflow"}},"end":"\\\\)","name":"meta.definition.method.signature.java","patterns":[{"begin":"(?=[^)])","end":"(?=\\\\))","name":"meta.method.parameters.groovy","patterns":[{"begin":"(?=[^),])","end":"(?=[),])","name":"meta.method.parameter.groovy","patterns":[{"match":",","name":"punctuation.definition.separator.groovy"},{"begin":"=","beginCaptures":{"0":{"name":"keyword.operator.assignment.groovy"}},"end":"(?=[),])","name":"meta.parameter.default.groovy","patterns":[{"include":"source.nextflow-groovy#groovy-code"}]},{"include":"source.nextflow-groovy#parameters"}]}]}]},{"begin":"(?=<)","end":"(?=\\\\s)","name":"meta.method.paramerised-type.groovy","patterns":[{"begin":"<","end":">","name":"storage.type.parameters.groovy","patterns":[{"include":"source.nextflow-groovy#types"},{"match":",","name":"punctuation.definition.seperator.groovy"}]}]},{"begin":"\\\\{","end":"(?=})","name":"meta.method.body.java","patterns":[{"include":"source.nextflow-groovy#groovy-code"}]}]},"function-def":{"applyEndPatternLast":1,"begin":"(?<=;|^|\\\\{)(?=\\\\s*(?:def|(?:(?:boolean|byte|char|short|int|float|long|double)|@?(?:[A-Za-z]\\\\w*\\\\.)*[A-Z]+\\\\w*)[]\\\\[]*(?:<.*>)?n)\\\\s+([^=]+\\\\s+)?\\\\w+\\\\s*\\\\()","end":"}|(?=[^{])","name":"meta.definition.method.groovy","patterns":[{"include":"#function-body"}]},"include-decl":{"patterns":[{"match":"^\\\\b(include)\\\\b","name":"keyword.nextflow"},{"match":"\\\\b(from)\\\\b","name":"keyword.nextflow"}]},"nextflow":{"patterns":[{"include":"#record-def"},{"include":"#enum-def"},{"include":"#function-def"},{"include":"#process-def"},{"include":"#workflow-def"},{"include":"#params-def"},{"include":"#output-def"},{"include":"#include-decl"},{"include":"source.nextflow-groovy"}]},"output-def":{"begin":"^\\\\s*(output)\\\\s*\\\\{","beginCaptures":{"1":{"name":"keyword.nextflow"}},"end":"}","name":"output.nextflow","patterns":[{"include":"source.nextflow-groovy#groovy"}]},"params-def":{"begin":"^\\\\s*(params)\\\\s*\\\\{","beginCaptures":{"1":{"name":"keyword.nextflow"}},"end":"}","name":"params.nextflow","patterns":[{"include":"source.nextflow-groovy#groovy"}]},"process-body":{"patterns":[{"match":"(?:input|output|when|script|shell|exec):","name":"constant.block.nextflow"},{"match":"\\\\b(val|env|file|path|stdin|stdout|tuple)([(\\\\s])","name":"entity.name.function.nextflow"},{"include":"source.nextflow-groovy#groovy"}]},"process-def":{"begin":"^\\\\s*(process)\\\\s+(\\\\w+)\\\\s*\\\\{","beginCaptures":{"1":{"name":"keyword.nextflow"},"2":{"name":"entity.name.function.nextflow"}},"end":"}","name":"process.nextflow","patterns":[{"include":"#process-body"}]},"record-def":{"begin":"^\\\\s*(record)\\\\s+(\\\\w+)\\\\s*\\\\{","beginCaptures":{"1":{"name":"keyword.nextflow"},"2":{"name":"storage.type.groovy"}},"end":"}","name":"record.nextflow","patterns":[{"include":"source.nextflow-groovy#groovy"}]},"workflow-body":{"patterns":[{"match":"(?:take|main|emit|publish):","name":"constant.block.nextflow"},{"include":"source.nextflow-groovy#groovy"}]},"workflow-def":{"begin":"^\\\\s*(workflow)(?:\\\\s+(\\\\w+))?\\\\s*\\\\{","beginCaptures":{"1":{"name":"keyword.nextflow"},"2":{"name":"entity.name.function.nextflow"}},"end":"}","name":"workflow.nextflow","patterns":[{"include":"#workflow-body"}]}},"scopeName":"source.nextflow","embeddedLangs":["nextflow-groovy"],"aliases":["nf"]}')),t=[...e,n];export{t as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
import{v as a}from"./chunk-ktx0nkhz.js";import"./chunk-gf0502ds.js";export{a as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
import{O as a}from"./chunk-ept66kdn.js";import"./chunk-gf0502ds.js";export{a as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
import"./chunk-gf0502ds.js";var e=Object.freeze(JSON.parse('{"displayName":"CODEOWNERS","name":"codeowners","patterns":[{"include":"#comment"},{"include":"#pattern"},{"include":"#owner"}],"repository":{"comment":{"patterns":[{"begin":"^\\\\s*#","captures":{"0":{"name":"punctuation.definition.comment.codeowners"}},"end":"$","name":"comment.line.codeowners"}]},"owner":{"match":"\\\\S*@\\\\S+","name":"storage.type.function.codeowners"},"pattern":{"match":"^\\\\s*(\\\\S+)","name":"variable.other.codeowners"}},"scopeName":"text.codeowners"}')),n=[e];export{n as default};

View file

@ -0,0 +1 @@
import"./chunk-gf0502ds.js";var e=Object.freeze(JSON.parse('{"displayName":"Gettext PO","fileTypes":["po","pot","potx"],"name":"po","patterns":[{"begin":"^(?:(?=(msg(?:id(_plural)?|ctxt))\\\\s*\\"[^\\"])|\\\\s*$)","end":"\\\\z","patterns":[{"include":"#body"}]},{"include":"#comments"},{"match":"^msg(id|str)\\\\s+\\"\\"\\\\s*$\\\\n?","name":"comment.line.number-sign.po"},{"captures":{"1":{"name":"constant.language.po"},"2":{"name":"punctuation.separator.key-value.po"},"3":{"name":"string.other.po"}},"match":"^\\"(?:([^:\\\\s]+)(:)\\\\s+)?([^\\"]*)\\"\\\\s*$\\\\n?","name":"meta.header.po"}],"repository":{"body":{"patterns":[{"begin":"^(msgid(_plural)?)\\\\s+","beginCaptures":{"1":{"name":"keyword.control.msgid.po"}},"end":"^(?!\\")","name":"meta.scope.msgid.po","patterns":[{"begin":"(\\\\G|^)\\"","end":"\\"","name":"string.quoted.double.po","patterns":[{"match":"\\\\\\\\[\\"\\\\\\\\]","name":"constant.character.escape.po"}]}]},{"begin":"^(msgstr)(?:(\\\\[)(\\\\d+)(]))?\\\\s+","beginCaptures":{"1":{"name":"keyword.control.msgstr.po"},"2":{"name":"keyword.control.msgstr.po"},"3":{"name":"constant.numeric.po"},"4":{"name":"keyword.control.msgstr.po"}},"end":"^(?!\\")","name":"meta.scope.msgstr.po","patterns":[{"begin":"(\\\\G|^)\\"","end":"\\"","name":"string.quoted.double.po","patterns":[{"match":"\\\\\\\\[\\"\\\\\\\\]","name":"constant.character.escape.po"}]}]},{"begin":"^(msgctxt)(?:(\\\\[)(\\\\d+)(]))?\\\\s+","beginCaptures":{"1":{"name":"keyword.control.msgctxt.po"},"2":{"name":"keyword.control.msgctxt.po"},"3":{"name":"constant.numeric.po"},"4":{"name":"keyword.control.msgctxt.po"}},"end":"^(?!\\")","name":"meta.scope.msgctxt.po","patterns":[{"begin":"(\\\\G|^)\\"","end":"\\"","name":"string.quoted.double.po","patterns":[{"match":"\\\\\\\\[\\"\\\\\\\\]","name":"constant.character.escape.po"}]}]},{"captures":{"1":{"name":"punctuation.definition.comment.po"}},"match":"^(#~).*$\\\\n?","name":"comment.line.number-sign.obsolete.po"},{"include":"#comments"},{"match":"^(?!\\\\s*$)[^\\"#].*$\\\\n?","name":"invalid.illegal.po"}]},"comments":{"patterns":[{"begin":"^(?=#)","end":"(?!\\\\G)","patterns":[{"begin":"(#,)\\\\s+","beginCaptures":{"1":{"name":"punctuation.definition.comment.po"}},"end":"\\\\n","name":"comment.line.number-sign.flag.po","patterns":[{"captures":{"1":{"name":"entity.name.type.flag.po"}},"match":"(?:\\\\G|,\\\\s*)(fuzzy|(?:no-)?(?:c|objc|sh|lisp|elisp|librep|scheme|smalltalk|java|csharp|awk|object-pascal|ycp|tcl|perl|perl-brace|php|gcc-internal|qt|boost)-format)"}]},{"begin":"#\\\\.","beginCaptures":{"0":{"name":"punctuation.definition.comment.po"}},"end":"\\\\n","name":"comment.line.number-sign.extracted.po"},{"begin":"(#:)[\\\\t ]*","beginCaptures":{"1":{"name":"punctuation.definition.comment.po"}},"end":"\\\\n","name":"comment.line.number-sign.reference.po","patterns":[{"match":"(\\\\S+:)([;\\\\d]*)","name":"storage.type.class.po"}]},{"begin":"#\\\\|","beginCaptures":{"0":{"name":"punctuation.definition.comment.po"}},"end":"\\\\n","name":"comment.line.number-sign.previous.po"},{"begin":"#","beginCaptures":{"0":{"name":"punctuation.definition.comment.po"}},"end":"\\\\n","name":"comment.line.number-sign.po"}]}]}},"scopeName":"source.po","aliases":["pot","potx"]}')),n=[e];export{n as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
import"./chunk-gf0502ds.js";var e=Object.freeze(JSON.parse('{"displayName":"Tcl","fileTypes":["tcl"],"foldingStartMarker":"\\\\{\\\\s*$","foldingStopMarker":"^\\\\s*}","name":"tcl","patterns":[{"begin":"(?<=^|;)\\\\s*((#))","beginCaptures":{"1":{"name":"comment.line.number-sign.tcl"},"2":{"name":"punctuation.definition.comment.tcl"}},"contentName":"comment.line.number-sign.tcl","end":"\\\\n","patterns":[{"match":"(\\\\\\\\[\\\\n\\\\\\\\])"}]},{"captures":{"1":{"name":"keyword.control.tcl"}},"match":"(?<=^|[;\\\\[{])\\\\s*(if|while|for|catch|default|return|break|continue|switch|exit|foreach|try|throw)\\\\b"},{"captures":{"1":{"name":"keyword.control.tcl"}},"match":"(?<=^|})\\\\s*(then|elseif|else)\\\\b"},{"captures":{"1":{"name":"keyword.other.tcl"},"2":{"name":"entity.name.function.tcl"}},"match":"(?<=^|\\\\{)\\\\s*(proc)\\\\s+(\\\\S+)"},{"captures":{"1":{"name":"keyword.other.tcl"}},"match":"(?<=^|[;\\\\[{])\\\\s*(after|append|array|auto_execok|auto_import|auto_load|auto_mkindex|auto_mkindex_old|auto_qualify|auto_reset|bgerror|binary|cd|clock|close|concat|dde|encoding|eof|error|eval|exec|expr|fblocked|fconfigure|fcopy|file|fileevent|filename|flush|format|gets|glob|global|history|http|incr|info|interp|join|lappend|library|lindex|linsert|list|llength|load|lrange|lreplace|lsearch|lset|lsort|memory|msgcat|namespace|open|package|parray|pid|pkg::create|pkg_mkIndex|proc|puts|pwd|re_syntax|read|registry|rename|resource|scan|seek|set|socket|SafeBase|source|split|string|subst|Tcl|tcl_endOfWord|tcl_findLibrary|tcl_startOfNextWord|tcl_startOfPreviousWord|tcl_wordBreakAfter|tcl_wordBreakBefore|tcltest|tclvars|tell|time|trace|unknown|unset|update|uplevel|upvar|variable|vwait)\\\\b"},{"begin":"(?<=^|[;\\\\[{])\\\\s*(reg(?:exp|sub))\\\\b\\\\s*","beginCaptures":{"1":{"name":"keyword.other.tcl"}},"end":"[]\\\\n;]","patterns":[{"match":"\\\\\\\\(?:.|\\\\n)","name":"constant.character.escape.tcl"},{"match":"-\\\\w+\\\\s*"},{"applyEndPatternLast":1,"begin":"--\\\\s*","end":"","patterns":[{"include":"#regexp"}]},{"include":"#regexp"}]},{"include":"#escape"},{"include":"#variable"},{"include":"#operator"},{"include":"#numeric"},{"begin":"\\"","beginCaptures":{"0":{"name":"punctuation.definition.string.begin.tcl"}},"end":"\\"","endCaptures":{"0":{"name":"punctuation.definition.string.end.tcl"}},"name":"string.quoted.double.tcl","patterns":[{"include":"#escape"},{"include":"#variable"},{"include":"#embedded"}]}],"repository":{"bare-string":{"begin":"(?:^|(?<=\\\\s))\\"","end":"\\"([^]\\\\s]*)","endCaptures":{"1":{"name":"invalid.illegal.tcl"}},"patterns":[{"include":"#escape"},{"include":"#variable"}]},"braces":{"begin":"(?:^|(?<=\\\\s))\\\\{","end":"}([^]\\\\s]*)","endCaptures":{"1":{"name":"invalid.illegal.tcl"}},"patterns":[{"match":"\\\\\\\\[\\\\n{}]","name":"constant.character.escape.tcl"},{"include":"#inner-braces"}]},"embedded":{"begin":"\\\\[","beginCaptures":{"0":{"name":"punctuation.section.embedded.begin.tcl"}},"end":"]","endCaptures":{"0":{"name":"punctuation.section.embedded.end.tcl"}},"name":"source.tcl.embedded","patterns":[{"include":"source.tcl"}]},"escape":{"match":"\\\\\\\\(\\\\d{1,3}|x\\\\h+|u\\\\h{1,4}|.|\\\\n)","name":"constant.character.escape.tcl"},"inner-braces":{"begin":"\\\\{","end":"}","patterns":[{"match":"\\\\\\\\[\\\\n{}]","name":"constant.character.escape.tcl"},{"include":"#inner-braces"}]},"numeric":{"match":"(?<![A-Za-z])([-+]?([0-9]*\\\\.)?[0-9]+f?)(?![.A-Za-z])","name":"constant.numeric.tcl"},"operator":{"match":"(?<=[ \\\\d])([-+~]|&{1,2}|\\\\|{1,2}|<{1,2}|>{1,2}|\\\\*{1,2}|[!%/]|<=|>=|={1,2}|!=|\\\\^)(?=[ \\\\d])","name":"keyword.operator.tcl"},"regexp":{"begin":"(?=\\\\S)(?![]\\\\n;])","end":"(?=[]\\\\n;])","patterns":[{"begin":"(?=[^\\\\t\\\\n ;])","end":"(?=[\\\\t\\\\n ;])","name":"string.regexp.tcl","patterns":[{"include":"#braces"},{"include":"#bare-string"},{"include":"#escape"},{"include":"#variable"}]},{"begin":"[\\\\t ]","end":"(?=[]\\\\n;])","patterns":[{"include":"#variable"},{"include":"#embedded"},{"include":"#escape"},{"include":"#braces"},{"include":"#string"}]}]},"string":{"applyEndPatternLast":1,"begin":"(?:^|(?<=\\\\s))(?=\\")","end":"","name":"string.quoted.double.tcl","patterns":[{"include":"#bare-string"}]},"variable":{"captures":{"1":{"name":"punctuation.definition.variable.tcl"}},"match":"(\\\\$)((?:[0-9A-Z_a-z]|::)+(\\\\([^)]+\\\\))?|\\\\{[^}]*})","name":"support.function.tcl"}},"scopeName":"source.tcl"}')),n=[e];export{n as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
import"./chunk-gf0502ds.js";var e=Object.freeze(JSON.parse('{"displayName":"Gleam","fileTypes":["gleam"],"name":"gleam","patterns":[{"include":"#comments"},{"include":"#keywords"},{"include":"#strings"},{"include":"#constant"},{"include":"#entity"},{"include":"#discards"}],"repository":{"binary_number":{"match":"\\\\b0[Bb][01_]*\\\\b","name":"constant.numeric.binary.gleam","patterns":[]},"comments":{"patterns":[{"match":"//.*","name":"comment.line.gleam"}]},"constant":{"patterns":[{"include":"#binary_number"},{"include":"#octal_number"},{"include":"#hexadecimal_number"},{"include":"#decimal_number"},{"match":"\\\\p{upper}\\\\p{alnum}*","name":"entity.name.type.gleam"}]},"decimal_number":{"match":"\\\\b([0-9][0-9_]*)(\\\\.([0-9_]*)?(e-?[0-9]+)?)?\\\\b","name":"constant.numeric.decimal.gleam","patterns":[]},"discards":{"match":"\\\\b_\\\\p{word}+{0,1}\\\\b","name":"comment.unused.gleam"},"entity":{"patterns":[{"begin":"\\\\b(\\\\p{lower}\\\\p{word}*)\\\\b\\\\s*\\\\(","captures":{"1":{"name":"entity.name.function.gleam"}},"end":"\\\\)","patterns":[{"include":"$self"}]},{"match":"\\\\b(\\\\p{lower}\\\\p{word}*):\\\\s","name":"variable.parameter.gleam"},{"match":"\\\\b(\\\\p{lower}\\\\p{word}*):","name":"entity.name.namespace.gleam"}]},"hexadecimal_number":{"match":"\\\\b0[Xx][_\\\\h]+\\\\b","name":"constant.numeric.hexadecimal.gleam","patterns":[]},"keywords":{"patterns":[{"match":"\\\\b(as|use|case|if|fn|import|let|assert|pub|type|opaque|const|todo|panic|else|echo)\\\\b","name":"keyword.control.gleam"},{"match":"(<-|->)","name":"keyword.operator.arrow.gleam"},{"match":"\\\\|>","name":"keyword.operator.pipe.gleam"},{"match":"\\\\.\\\\.","name":"keyword.operator.splat.gleam"},{"match":"([!=]=)","name":"keyword.operator.comparison.gleam"},{"match":"([<>]=?\\\\.)","name":"keyword.operator.comparison.float.gleam"},{"match":"(<=|>=|[<>])","name":"keyword.operator.comparison.int.gleam"},{"match":"(&&|\\\\|\\\\|)","name":"keyword.operator.logical.gleam"},{"match":"<>","name":"keyword.operator.string.gleam"},{"match":"\\\\|","name":"keyword.operator.other.gleam"},{"match":"([-*+/]\\\\.)","name":"keyword.operator.arithmetic.float.gleam"},{"match":"([-%*+/])","name":"keyword.operator.arithmetic.int.gleam"},{"match":"=","name":"keyword.operator.assignment.gleam"}]},"octal_number":{"match":"\\\\b0[Oo][0-7_]*\\\\b","name":"constant.numeric.octal.gleam","patterns":[]},"strings":{"begin":"\\"","end":"\\"","name":"string.quoted.double.gleam","patterns":[{"match":"\\\\\\\\.","name":"constant.character.escape.gleam"}]}},"scopeName":"source.gleam"}')),a=[e];export{a as default};

View file

@ -0,0 +1 @@
import{Y as a}from"./chunk-1ehq66yp.js";import"./chunk-xg9nsz1a.js";import"./chunk-z868q2s0.js";import"./chunk-gf0502ds.js";export{a as default};

View file

@ -0,0 +1 @@
import"./chunk-gf0502ds.js";var e=Object.freeze(JSON.parse('{"displayName":"QML Directory","name":"qmldir","patterns":[{"include":"#comment"},{"include":"#keywords"},{"include":"#version"},{"include":"#names"}],"repository":{"comment":{"patterns":[{"begin":"#","end":"$","name":"comment.line.number-sign.qmldir"}]},"file-name":{"patterns":[{"match":"\\\\b\\\\w+\\\\.(qmltypes|qml|js)\\\\b","name":"string.unquoted.qmldir"}]},"identifier":{"patterns":[{"match":"\\\\b\\\\w+\\\\b","name":"variable.parameter.qmldir"}]},"keywords":{"patterns":[{"match":"\\\\b(module|singleton|internal|plugin|classname|typeinfo|depends|designersupported)\\\\b","name":"keyword.other.qmldir"}]},"module-name":{"patterns":[{"match":"\\\\b[A-Z]\\\\w*\\\\b","name":"entity.name.type.qmldir"}]},"names":{"patterns":[{"include":"#file-name"},{"include":"#module-name"},{"include":"#identifier"}]},"version":{"patterns":[{"match":"\\\\b\\\\d+\\\\.\\\\d+\\\\b","name":"constant.numeric.qml"}]}},"scopeName":"source.qmldir"}')),n=[e];export{n as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
import{G as n}from"./chunk-z9jws129.js";import{N as t}from"./chunk-71s03bbh.js";import{Y as e}from"./chunk-1ehq66yp.js";import"./chunk-xg9nsz1a.js";import"./chunk-z868q2s0.js";import"./chunk-gf0502ds.js";var a=Object.freeze(JSON.parse('{"displayName":"Edge","injections":{"text.html.edge - (meta.embedded | meta.tag | comment.block.edge), L:(text.html.edge meta.tag - (comment.block.edge | meta.embedded.block.edge)), L:(source.ts.embedded.html - (comment.block.edge | meta.embedded.block.edge))":{"patterns":[{"include":"#comment"},{"include":"#escapedMustache"},{"include":"#safeMustache"},{"include":"#mustache"},{"include":"#nonSeekableTag"},{"include":"#tag"}]}},"name":"edge","patterns":[{"include":"text.html.basic"},{"include":"text.html.derivative"}],"repository":{"comment":{"begin":"\\\\{\\\\{--","beginCaptures":{"0":{"name":"punctuation.definition.comment.begin.edge"}},"end":"--}}","endCaptures":{"0":{"name":"punctuation.definition.comment.end.edge"}},"name":"comment.block"},"escapedMustache":{"begin":"@\\\\{\\\\{","beginCaptures":{"0":{"name":"punctuation.definition.comment.begin.edge"}},"end":"}}","endCaptures":{"0":{"name":"punctuation.definition.comment.end.edge"}},"name":"comment.block"},"mustache":{"begin":"\\\\{\\\\{","beginCaptures":{"0":{"name":"punctuation.mustache.begin"}},"end":"}}","endCaptures":{"0":{"name":"punctuation.mustache.end"}},"name":"meta.embedded.block.javascript","patterns":[{"include":"source.ts#expression"}]},"nonSeekableTag":{"captures":{"2":{"name":"support.function.edge"}},"match":"^(\\\\s*)((@{1,2})(!)?([.A-Z_a-z]+))(~)?$","name":"meta.embedded.block.javascript","patterns":[{"include":"source.ts#expression"}]},"safeMustache":{"begin":"\\\\{\\\\{\\\\{","beginCaptures":{"0":{"name":"punctuation.mustache.begin"}},"end":"}}}","endCaptures":{"0":{"name":"punctuation.mustache.end"}},"name":"meta.embedded.block.javascript","patterns":[{"include":"source.ts#expression"}]},"tag":{"begin":"^(\\\\s*)((@{1,2})(!)?([.A-Z_a-z]+)(\\\\s{0,2}))(\\\\()","beginCaptures":{"2":{"name":"support.function.edge"},"7":{"name":"punctuation.paren.open"}},"end":"\\\\)","endCaptures":{"0":{"name":"punctuation.paren.close"}},"name":"meta.embedded.block.javascript","patterns":[{"include":"source.ts#expression"}]}},"scopeName":"text.html.edge","embeddedLangs":["typescript","html","html-derivative"]}')),i=[...t,...e,...n,a];export{i as default};

View file

@ -0,0 +1 @@
import"./chunk-gf0502ds.js";var t=Object.freeze(JSON.parse('{"displayName":"TSV","fileTypes":["tsv","tab"],"name":"tsv","patterns":[{"captures":{"1":{"name":"rainbow1"},"2":{"name":"keyword.rainbow2"},"3":{"name":"entity.name.function.rainbow3"},"4":{"name":"comment.rainbow4"},"5":{"name":"string.rainbow5"},"6":{"name":"variable.parameter.rainbow6"},"7":{"name":"constant.numeric.rainbow7"},"8":{"name":"entity.name.type.rainbow8"},"9":{"name":"markup.bold.rainbow9"},"10":{"name":"invalid.rainbow10"}},"match":"([^\\\\t]*\\\\t?)([^\\\\t]*\\\\t?)([^\\\\t]*\\\\t?)([^\\\\t]*\\\\t?)([^\\\\t]*\\\\t?)([^\\\\t]*\\\\t?)([^\\\\t]*\\\\t?)([^\\\\t]*\\\\t?)([^\\\\t]*\\\\t?)([^\\\\t]*\\\\t?)","name":"rainbowgroup"}],"scopeName":"text.tsv"}')),a=[t];export{a as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
import{k as a}from"./chunk-pce8yxd3.js";import"./chunk-gf0502ds.js";export{a as default};

View file

@ -0,0 +1 @@
import"./chunk-gf0502ds.js";var e=Object.freeze(JSON.parse('{"displayName":"Rel","name":"rel","patterns":[{"include":"#strings"},{"include":"#comment"},{"include":"#single-line-comment-consuming-line-ending"},{"include":"#deprecated-temporary"},{"include":"#operators"},{"include":"#symbols"},{"include":"#keywords"},{"include":"#otherkeywords"},{"include":"#types"},{"include":"#constants"}],"repository":{"comment":{"patterns":[{"begin":"/\\\\*\\\\*(?!/)","beginCaptures":{"0":{"name":"punctuation.definition.comment.rel"}},"end":"\\\\*/","endCaptures":{"0":{"name":"punctuation.definition.comment.rel"}},"name":"comment.block.documentation.rel","patterns":[{"include":"#docblock"}]},{"begin":"(/\\\\*)(?:\\\\s*((@)internal)(?=\\\\s|(\\\\*/)))?","beginCaptures":{"1":{"name":"punctuation.definition.comment.rel"},"2":{"name":"storage.type.internaldeclaration.rel"},"3":{"name":"punctuation.decorator.internaldeclaration.rel"}},"end":"\\\\*/","endCaptures":{"0":{"name":"punctuation.definition.comment.rel"}},"name":"comment.block.rel"},{"begin":"doc\\"\\"\\"","end":"\\"\\"\\"","name":"comment.block.documentation.rel"},{"begin":"(^[\\\\t ]+)?((//)(?:\\\\s*((@)internal)(?=\\\\s|$))?)","beginCaptures":{"1":{"name":"punctuation.whitespace.comment.leading.rel"},"2":{"name":"comment.line.double-slash.rel"},"3":{"name":"punctuation.definition.comment.rel"},"4":{"name":"storage.type.internaldeclaration.rel"},"5":{"name":"punctuation.decorator.internaldeclaration.rel"}},"contentName":"comment.line.double-slash.rel","end":"(?=$)"}]},"constants":{"patterns":[{"match":"\\\\b((true|false))\\\\b","name":"constant.language.rel"}]},"deprecated-temporary":{"patterns":[{"match":"@inspect","name":"keyword.other.rel"}]},"keywords":{"patterns":[{"match":"\\\\b((def|entity|bound|include|ic|forall|exists|[∀∃]|return|module|^end))\\\\b|(((<)?\\\\|(>)?)|[∀∃])","name":"keyword.control.rel"}]},"operators":{"patterns":[{"match":"\\\\b((if|then|else|and|or|not|eq|neq|lt|lt_eq|gt|gt_eq))\\\\b|([-%*+/=^÷]|!=|[<≠]|<=|[>≤]|>=|[\\\\&≥])|\\\\s+(end)","name":"keyword.other.rel"}]},"otherkeywords":{"patterns":[{"match":"\\\\s*(@inline)\\\\s*|\\\\s*(@auto_number)\\\\s*|\\\\s*(function)\\\\s|\\\\b((implies|select|from|∈|where|for|in))\\\\b|(((<)?\\\\|(>)?)|∈)","name":"keyword.other.rel"}]},"single-line-comment-consuming-line-ending":{"begin":"(^[\\\\t ]+)?((//)(?:\\\\s*((@)internal)(?=\\\\s|$))?)","beginCaptures":{"1":{"name":"punctuation.whitespace.comment.leading.rel"},"2":{"name":"comment.line.double-slash.rel"},"3":{"name":"punctuation.definition.comment.rel"},"4":{"name":"storage.type.internaldeclaration.rel"},"5":{"name":"punctuation.decorator.internaldeclaration.rel"}},"contentName":"comment.line.double-slash.rel","end":"(?=^)"},"strings":{"begin":"\\"","end":"\\"","name":"string.quoted.double.rel","patterns":[{"match":"\\\\\\\\.","name":"constant.character.escape.rel"}]},"symbols":{"patterns":[{"match":"(:[$\\\\[_[:alpha:]](]|[$_[:alnum:]]*))","name":"variable.parameter.rel"}]},"types":{"patterns":[{"match":"\\\\b((Symbol|Char|Bool|Rational|FixedDecimal|Float16|Float32|Float64|Int8|Int16|Int32|Int64|Int128|UInt8|UInt16|UInt32|UInt64|UInt128|Date|DateTime|Day|Week|Month|Year|Nanosecond|Microsecond|Millisecond|Second|Minute|Hour|FilePos|HashValue|AutoNumberValue))\\\\b","name":"entity.name.type.rel"}]}},"scopeName":"source.rel"}')),n=[e];export{n as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
import{s as a}from"./chunk-crmnbecm.js";import"./chunk-0gpjqeyh.js";import"./chunk-nkw6kj41.js";import"./chunk-71s03bbh.js";import"./chunk-z868q2s0.js";import"./chunk-gf0502ds.js";export{a as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
import"./chunk-gf0502ds.js";var e=Object.freeze(JSON.parse('{"displayName":"Berry","name":"berry","patterns":[{"include":"#controls"},{"include":"#strings"},{"include":"#comment-block"},{"include":"#comments"},{"include":"#keywords"},{"include":"#function"},{"include":"#member"},{"include":"#identifier"},{"include":"#number"},{"include":"#operator"}],"repository":{"comment-block":{"begin":"#-","end":"-#","name":"comment.berry","patterns":[{}]},"comments":{"begin":"#","end":"\\\\n","name":"comment.line.berry","patterns":[{}]},"controls":{"patterns":[{"match":"\\\\b(if|elif|else|for|while|do|end|break|continue|return|try|except|raise)\\\\b","name":"keyword.control.berry"}]},"function":{"patterns":[{"match":"\\\\b([A-Z_a-z][0-9A-Z_a-z]*(?=\\\\s*\\\\())","name":"entity.name.function.berry"}]},"identifier":{"patterns":[{"match":"\\\\b[A-Z_a-z]\\\\w+\\\\b","name":"identifier.berry"}]},"keywords":{"patterns":[{"match":"\\\\b(var|static|def|class|true|false|nil|self|super|import|as|_class)\\\\b","name":"keyword.berry"}]},"member":{"patterns":[{"captures":{"0":{"name":"entity.other.attribute-name.berry"}},"match":"\\\\.([A-Z_a-z][0-9A-Z_a-z]*)"}]},"number":{"patterns":[{"match":"0x\\\\h+|\\\\d+|(\\\\d+\\\\.?|\\\\.\\\\d)\\\\d*([Ee][-+]?\\\\d+)?","name":"constant.numeric.berry"}]},"operator":{"patterns":[{"match":"[-\\\\]!%\\\\&(-+./:<=>\\\\[^|~]","name":"keyword.operator.berry"}]},"strings":{"patterns":[{"begin":"f(?=[\\"\'])","patterns":[{"begin":"\\"","end":"\\"","name":"string.quoted.other.berry","patterns":[{"match":"(\\\\\\\\x\\\\h{2})|(\\\\\\\\[0-7]{3})|(\\\\\\\\\\\\\\\\)|(\\\\\\\\\\")|(\\\\\\\\\')|(\\\\\\\\a)|(\\\\\\\\b)|(\\\\\\\\f)|(\\\\\\\\n)|(\\\\\\\\r)|(\\\\\\\\t)|(\\\\\\\\v)","name":"constant.character.escape.berry"},{"match":"\\\\{\\\\{[^}]*}}","name":"string.quoted.other.berry"},{"begin":"\\\\{","end":"}","name":"keyword.other.unit.berry","patterns":[{"include":"#keywords"},{"include":"#numbers"},{"include":"#identifier"},{"include":"#operator"},{"include":"#member"},{"include":"#function"}]}]},{"begin":"\'","end":"\'","name":"string.quoted.other.berry","patterns":[{"match":"(\\\\\\\\x\\\\h{2})|(\\\\\\\\[0-7]{3})|(\\\\\\\\\\\\\\\\)|(\\\\\\\\\\")|(\\\\\\\\\')|(\\\\\\\\a)|(\\\\\\\\b)|(\\\\\\\\f)|(\\\\\\\\n)|(\\\\\\\\r)|(\\\\\\\\t)|(\\\\\\\\v)","name":"constant.character.escape.berry"},{"match":"\\\\{\\\\{[^}]*}}","name":"string.quoted.other.berry"},{"begin":"\\\\{","end":"}","name":"keyword.other.unit.berry","patterns":[{"include":"#keywords"},{"include":"#numbers"},{"include":"#identifier"},{"include":"#operator"},{"include":"#member"},{"include":"#function"}]}]}],"while":"\\\\G|^[\\\\t ]*(?=[\\"\'])"},{"begin":"([\\"\'])","end":"\\\\1","name":"string.quoted.double.berry","patterns":[{"match":"(\\\\\\\\x\\\\h{2})|(\\\\\\\\[0-7]{3})|(\\\\\\\\\\\\\\\\)|(\\\\\\\\\\")|(\\\\\\\\\')|(\\\\\\\\a)|(\\\\\\\\b)|(\\\\\\\\f)|(\\\\\\\\n)|(\\\\\\\\r)|(\\\\\\\\t)|(\\\\\\\\v)","name":"constant.character.escape.berry"}]}]}},"scopeName":"source.berry","aliases":["be"]}')),r=[e];export{r as default};

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
import{B as e}from"./chunk-xsvv7xvt.js";import"./chunk-gf0502ds.js";var s=Object.freeze(JSON.parse('{"displayName":"Shell Session","fileTypes":["sh-session"],"name":"shellsession","patterns":[{"captures":{"1":{"name":"entity.other.prompt-prefix.shell-session"},"2":{"name":"punctuation.separator.prompt.shell-session"},"3":{"name":"source.shell","patterns":[{"include":"source.shell"}]}},"match":"^(?:((?:\\\\(\\\\S+\\\\)\\\\s*)?(?:sh\\\\S*?|\\\\w+\\\\S+[:@]\\\\S+(?:\\\\s+\\\\S+)?|\\\\[\\\\S+?[:@]\\\\N+?].*?))\\\\s*)?([#$%>❯➜\\\\p{Greek}])\\\\s+(.*)$"},{"match":"^.+$","name":"meta.output.shell-session"}],"scopeName":"text.shell-session","embeddedLangs":["shellscript"],"aliases":["console"]}')),t=[...e,s];export{t as default};

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
import{l as a}from"./chunk-6v64ydme.js";import"./chunk-gf0502ds.js";export{a as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
import{F as a}from"./chunk-y949271p.js";import"./chunk-gf0502ds.js";export{a as default};

View file

@ -0,0 +1 @@
import{u as a}from"./chunk-8veqp2gt.js";import"./chunk-gf0502ds.js";export{a as default};

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
import"./chunk-gf0502ds.js";var e=Object.freeze(JSON.parse('{"displayName":"Wenyan","name":"wenyan","patterns":[{"include":"#keywords"},{"include":"#constants"},{"include":"#operators"},{"include":"#symbols"},{"include":"#expression"},{"include":"#comment-blocks"},{"include":"#comment-lines"}],"repository":{"comment-blocks":{"begin":"([批注疏]曰)。?(「「|『)","end":"(」」|』)","name":"comment.block","patterns":[{"match":"\\\\\\\\.","name":"constant.character"}]},"comment-lines":{"begin":"[批注疏]曰","end":"$","name":"comment.line","patterns":[{"match":"\\\\\\\\.","name":"constant.character"}]},"constants":{"patterns":[{"match":"[·〇一七三九二五京億兆八六分十千又四垓埃塵微忽極正毫沙渺溝漠澗百秭穰絲纖萬負載釐零]","name":"constant.numeric"},{"match":"[其陰陽]","name":"constant.language"},{"begin":"「「|『","end":"」」|』","name":"string.quoted","patterns":[{"match":"\\\\\\\\.","name":"constant.character"}]}]},"expression":{"patterns":[{"include":"#variables"}]},"keywords":{"patterns":[{"match":"[元列數爻物術言]","name":"storage.type"},{"match":"乃行是術曰|若其不然者|乃歸空無|欲行是術|乃止是遍|若其然者|其物如是|乃得矣|之術也|必先得|是術曰|恆為是|之物也|乃得|是謂|云云|中之|為是|乃止|若非|或若|之長|其餘","name":"keyword.control"},{"match":"或云|蓋謂","name":"keyword.control"},{"match":"中有陽乎|中無陰乎|所餘幾何|不等於|不大於|不小於|等於|大於|小於|[乘以加於減變除]","name":"keyword.operator"},{"match":"不知何禍歟|不復存矣|姑妄行此|如事不諧|名之曰|吾嘗觀|之禍歟|乃作罷|吾有|今有|物之|書之|以施|昔之|是矣|之書|方悟|之義|嗚呼|之禍|[中今取噫夫施曰有豈]","name":"keyword.other"},{"match":"[之也充凡者若遍銜]","name":"keyword.control"}]},"symbols":{"patterns":[{"match":"[、。]","name":"punctuation.separator"}]},"variables":{"begin":"「","end":"」","name":"variable.other","patterns":[{"match":"\\\\\\\\.","name":"constant.character"}]}},"scopeName":"source.wenyan","aliases":["文言"]}')),n=[e];export{n as default};

View file

@ -0,0 +1 @@
import"./chunk-gf0502ds.js";var e=Object.freeze(JSON.parse('{"displayName":"Tasl","fileTypes":["tasl"],"name":"tasl","patterns":[{"include":"#comment"},{"include":"#namespace"},{"include":"#type"},{"include":"#class"},{"include":"#edge"}],"repository":{"class":{"begin":"^\\\\s*(class)\\\\b","beginCaptures":{"1":{"name":"keyword.control.tasl.class"}},"end":"$","patterns":[{"include":"#key"},{"include":"#export"},{"include":"#expression"}]},"comment":{"captures":{"1":{"name":"punctuation.definition.comment.tasl"}},"match":"(#).*$","name":"comment.line.number-sign.tasl"},"component":{"begin":"->","beginCaptures":{"0":{"name":"punctuation.separator.tasl.component"}},"end":"$","patterns":[{"include":"#expression"}]},"coproduct":{"begin":"\\\\[","beginCaptures":{"0":{"name":"punctuation.definition.block.tasl.coproduct"}},"end":"]","endCaptures":{"0":{"name":"punctuation.definition.block.tasl.coproduct"}},"patterns":[{"include":"#comment"},{"include":"#term"},{"include":"#option"}]},"datatype":{"match":"[A-Za-z][0-9A-Za-z]*:(?:[!$\\\\&-;=?-Z_a-z~]|%\\\\h{2})+","name":"string.regexp"},"edge":{"begin":"^\\\\s*(edge)\\\\b","beginCaptures":{"1":{"name":"keyword.control.tasl.edge"}},"end":"$","patterns":[{"include":"#key"},{"include":"#export"},{"match":"=/","name":"punctuation.separator.tasl.edge.source"},{"match":"/=>","name":"punctuation.separator.tasl.edge.target"},{"match":"=>","name":"punctuation.separator.tasl.edge"},{"include":"#expression"}]},"export":{"match":"::","name":"keyword.operator.tasl.export"},"expression":{"patterns":[{"include":"#literal"},{"include":"#uri"},{"include":"#product"},{"include":"#coproduct"},{"include":"#reference"},{"include":"#optional"},{"include":"#identifier"}]},"identifier":{"captures":{"1":{"name":"variable"}},"match":"([A-Za-z][0-9A-Za-z]*)\\\\b"},"key":{"match":"[A-Za-z][0-9A-Za-z]*:(?:[!$\\\\&-;=?-Z_a-z~]|%\\\\h{2})+","name":"markup.bold entity.name.class"},"literal":{"patterns":[{"include":"#datatype"}]},"namespace":{"captures":{"1":{"name":"keyword.control.tasl.namespace"},"2":{"patterns":[{"include":"#namespaceURI"},{"match":"[A-Za-z][0-9A-Za-z]*\\\\b","name":"entity.name"}]}},"match":"^\\\\s*(namespace)\\\\b(.*)"},"namespaceURI":{"match":"[a-z]+:[]!#-;=?-\\\\[_a-z~]+","name":"markup.underline.link"},"option":{"begin":"<-","beginCaptures":{"0":{"name":"punctuation.separator.tasl.option"}},"end":"$","patterns":[{"include":"#expression"}]},"optional":{"begin":"\\\\?","beginCaptures":{"0":{"name":"keyword.operator"}},"end":"$","patterns":[{"include":"#expression"}]},"product":{"begin":"\\\\{","beginCaptures":{"0":{"name":"punctuation.definition.block.tasl.product"}},"end":"}","endCaptures":{"0":{"name":"punctuation.definition.block.tasl.product"}},"patterns":[{"include":"#comment"},{"include":"#term"},{"include":"#component"}]},"reference":{"captures":{"1":{"name":"markup.bold keyword.operator"},"2":{"patterns":[{"include":"#key"}]}},"match":"(\\\\*)\\\\s*(.*)"},"term":{"match":"[A-Za-z][0-9A-Za-z]*:(?:[!$\\\\&-;=?-Z_a-z~]|%\\\\h{2})+","name":"entity.other.tasl.key"},"type":{"begin":"^\\\\s*(type)\\\\b","beginCaptures":{"1":{"name":"keyword.control.tasl.type"}},"end":"$","patterns":[{"include":"#expression"}]},"uri":{"match":"<>","name":"variable.other.constant"}},"scopeName":"source.tasl"}')),n=[e];export{n as default};

View file

@ -0,0 +1 @@
import{y as a}from"./chunk-vxrqpknz.js";import"./chunk-fgccx1yw.js";import"./chunk-9nqxn300.js";import"./chunk-a4mrrp97.js";import"./chunk-z1p7fbkb.js";import"./chunk-gf0502ds.js";export{a as default};

View file

@ -0,0 +1 @@
import{j as e}from"./chunk-tcwzycpt.js";import"./chunk-gf0502ds.js";var n=Object.freeze(JSON.parse('{"displayName":"HXML","fileTypes":["hxml"],"foldingStartMarker":"--next","foldingStopMarker":"\\\\n\\\\n","name":"hxml","patterns":[{"captures":{"1":{"name":"punctuation.definition.comment.hxml"}},"match":"(#).*$\\\\n?","name":"comment.line.number-sign.hxml"},{"begin":"(?<!\\\\w)(--macro)\\\\b","beginCaptures":{"1":{"name":"keyword.other.hxml"}},"end":"\\\\n","patterns":[{"include":"source.hx#block-contents"}]},{"captures":{"1":{"name":"keyword.other.hxml"},"2":{"name":"support.package.hx"},"4":{"name":"entity.name.type.hx"}},"match":"(?<!\\\\w)(-(?:m|main|-main|-run))\\\\b\\\\s*\\\\b(?:(([a-z][0-9A-Za-z]*\\\\.)*)(_*[A-Z]\\\\w*))?\\\\b"},{"captures":{"1":{"name":"keyword.other.hxml"}},"match":"(?<!\\\\w)(-(?:cppia|cpp?|js|as3|swf-(header|version|lib(-extern)?)|swf9?|neko|python|php|cs|java-lib|java|xml|lua|hl|x|lib|D|resource|exclude|version|v|debug|prompt|cmd|dce\\\\s+(std|full|no)?|-flash-strict|-no-traces|-flash-use-stage|-neko-source|-gen-hx-classes|net-lib|net-std|c-arg|-each|-next|-display|-no-output|-times|-no-inline|-no-opt|-php-front|-php-lib|-php-prefix|-remap|-help-defines|-help-metas|help|-help|java|cs|-js-modern|-interp|-eval|-dce|-wait|-connect|-cwd|-run)).*$"},{"captures":{"1":{"name":"keyword.other.hxml"}},"match":"(?<!\\\\w)(-(?:-js(on)?|-lua|-swf-(header|version|lib(-extern)?)|-swf|-as3|-neko|-php|-cppia|-cpp|-cppia|-cs|-java-lib(-extern)?|-java|-jvm|-python|-hl|p|-class-path|L|-library|-define|r|-resource|-cmd|C|-verbose|-debug|-prompt|-xml|-json|-net-lib|-net-std|-c-arg|-version|-haxelib-global|h|-main|-server-connect|-server-listen)).*$"}],"scopeName":"source.hxml","embeddedLangs":["haxe"]}')),t=[...e,n];export{t as default};

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
import"./chunk-gf0502ds.js";var e=Object.freeze(JSON.parse(`{"displayName":"OpenSCAD","fileTypes":["scad"],"foldingStartMarker":"/\\\\*\\\\*|\\\\{\\\\s*$","foldingStopMarker":"\\\\*\\\\*/|^\\\\s*}","name":"openscad","patterns":[{"captures":{"1":{"name":"keyword.control.scad"}},"match":"^(module)\\\\s.*$","name":"meta.function.scad"},{"match":"\\\\b(if|else|for|intersection_for|assign|render|function|include|use)\\\\b","name":"keyword.control.scad"},{"begin":"/\\\\*\\\\*(?!/)","captures":{"0":{"name":"punctuation.definition.comment.scad"}},"end":"\\\\*/","name":"comment.block.documentation.scad"},{"begin":"/\\\\*","captures":{"0":{"name":"punctuation.definition.comment.scad"}},"end":"\\\\*/","name":"comment.block.scad"},{"captures":{"1":{"name":"punctuation.definition.comment.scad"}},"match":"(//).*$\\\\n?","name":"comment.line.double-slash.scad"},{"begin":"\\"","end":"\\"","name":"string.quoted.double.scad","patterns":[{"match":"\\\\\\\\.","name":"constant.character.escape.scad"}]},{"begin":"'","beginCaptures":{"0":{"name":"punctuation.definition.string.begin.scad"}},"end":"'","endCaptures":{"0":{"name":"punctuation.definition.string.end.scad"}},"name":"string.quoted.single.scad","patterns":[{"match":"\\\\\\\\(x\\\\h{2}|[012][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)","name":"constant.character.escape.scad"}]},{"begin":"\\"","beginCaptures":{"0":{"name":"punctuation.definition.string.begin.scad"}},"end":"\\"","endCaptures":{"0":{"name":"punctuation.definition.string.end.scad"}},"name":"string.quoted.double.scad","patterns":[{"match":"\\\\\\\\(x\\\\h{2}|[012][0-7]{0,2}|3[0-6][0-7]|37[0-7]?|[4-7][0-7]?|.)","name":"constant.character.escape.scad"}]},{"match":"\\\\b(abs|acos|asun|atan2??|ceil|cos|exp|floor|ln|log|lookup|max|min|pow|rands|round|sign|sin|sqrt|tan|str|cube|sphere|cylinder|polyhedron|scale|rotate|translate|mirror|multimatrix|color|minkowski|hull|union|difference|intersection|echo)\\\\b","name":"support.function.scad"},{"match":";","name":"punctuation.terminator.statement.scad"},{"match":",[\\\\t |]*","name":"meta.delimiter.object.comma.scad"},{"match":"\\\\.","name":"meta.delimiter.method.period.scad"},{"match":"[{}]","name":"meta.brace.curly.scad"},{"match":"[()]","name":"meta.brace.round.scad"},{"match":"[]\\\\[]","name":"meta.brace.square.scad"},{"match":"[!$%\\\\&*]|--?|\\\\+\\\\+|[+~]|===?|=|!==??|<=|>=|<<=|>>=|>>>=|<>|[!<>]|&&|\\\\|\\\\||\\\\?:|\\\\*=|(?<!\\\\()/=|%=|\\\\+=|-=|&=|\\\\^=|\\\\b(in|instanceof|new|delete|typeof|void)\\\\b","name":"keyword.operator.scad"},{"match":"\\\\b((0([Xx])\\\\h+)|([0-9]+(\\\\.[0-9]+)?))\\\\b","name":"constant.numeric.scad"},{"match":"\\\\btrue\\\\b","name":"constant.language.boolean.true.scad"},{"match":"\\\\bfalse\\\\b","name":"constant.language.boolean.false.scad"}],"scopeName":"source.scad","aliases":["scad"]}`)),a=[e];export{a as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
import{Z as a}from"./chunk-xg9nsz1a.js";import"./chunk-gf0502ds.js";export{a as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show more