šŸ“° Topics

今週ćÆćƒ¬ćƒćƒ¼ćƒˆć®åŠåˆ†ćŒRust恧CLIćƒ„ćƒ¼ćƒ«ć‚’ä½œć£ć¦å­¦ć‚“ć ć“ćØ恧恙怂
ēµ¦é›»ćØHDMIå‡ŗåŠ›ć‚’å…¼ć­ćŸé«˜ę€§čƒ½ćŖUSB TYpe-C惏惖悂ć‚Ŗć‚¹ć‚¹ćƒ”ć€‚

Table of Contents

ę›ø恄恟恓ćØ

ćŖ恗怂

å­¦ć‚“ć ć“ćØ

怐Rust怑CLIć‚’ä½œć£ć¦ćæ恟

Rust恧AtLrusćØ恄恆CLIćƒ„ćƒ¼ćƒ«ć‚’ä½œć£ć¦ćæć¾ć—ćŸć€‚
README恫čŖ¬ę˜Žć‚‚ćŖćć€ćƒćƒ¼ć‚øćƒ§ćƒ‹ćƒ³ć‚°ć‚‚ć—ć¦ć„ć¾ć›ć‚“ćŒä»„äø‹ćŒćƒŖ惝ć‚ø惈ćƒŖ恧恙怂

開ē™ŗć‚’é€šć—ć¦ć„ćć¤ć‹ć®ć“ćØć‚’å­¦ć³ć¾ć—ćŸć€‚

å¼•ę•°ć®ćƒ‘ćƒ¼ć‚¹

structopt悒ä½æć„ć¾ć™ć€‚

ę§‹é€ ä½“ć«ć‚³ćƒžćƒ³ćƒ‰ćƒ©ć‚¤ćƒ³å¼•ę•°ć®ä»•ę§˜ć‚’å®£čØ€ć™ć‚‹ćØ态Args::from_args()恙悌恰OK怂

use std::path::PathBuf;
use structopt::StructOpt;

// ... äø­ē•„

#[derive(Debug, StructOpt)]
struct Args {
    /// Input parameter json file
    #[structopt(parse(from_os_str))]
    input: PathBuf,
}

#[tokio::main]
async fn main() -> Result<()> {
    // ... äø­ē•„

    let args: Args = Args::from_args();
    let json_str = fs::read_to_string(&args.input)?;

    // ... äø­ē•„
}

ä»Šå›žć®ćƒ„ćƒ¼ćƒ«ćÆå…„åŠ›ć®jsonćƒ•ć‚”ć‚¤ćƒ«ćƒ‘ć‚¹ć ć‘ć§ć™ćŒć€å¼•ę•°ćŒå¢—ćˆć‚‹ćØä¾æåˆ©ć§ć™ć€‚

JSONć®ćƒ‘ćƒ¼ć‚¹

serde-rs/json悒ä½æć„ć¾ć™ć€‚

刄途serdeć®ć‚¤ćƒ³ć‚¹ćƒˆćƒ¼ćƒ«ć‚‚åæ…要恧恙怂

serde恮Serialize/Deserialize悒ä½æ恆恟悁态Cargo.toml恮featuresęŒ‡å®šćŒåæ…要恧恙怂

serde_json = "1.0.57"
serde = { version = "1.0.115", features = ["derive"] }

JSON恮꧋造悒#[derive(Deserialize)]ć®ć¤ć„ćŸstructć§å®šē¾©ć—ć¾ć™ć€‚
serde_json::from_str悒ä½æć£ć¦ęŒ‡å®šć—ćŸåž‹ć«å¤‰ę›ć§ćć¾ć™ć€‚

use serde::Deserialize;

// ... äø­ē•„

#[derive(Deserialize, Debug)]
struct Group {
    slug: String,
    emails: Vec<String>,
}

#[derive(Deserialize, Debug)]
struct CreateGroupsOperation {
    workspace_uuid: String,
    group_names: Vec<String>,
}

#[derive(Deserialize, Debug)]
struct InviteMembersOperation {
    /// Ex: tadashi-aikawa/x-viewer
    repository: String,
    /// Ex: read, write
    permission: String,
    emails: Vec<String>,
}

#[derive(Deserialize, Debug)]
struct AddGroupMembersOperation {
    workspace_uuid: String,
    groups: Vec<Group>,
}

#[derive(Deserialize, Debug)]
struct Operation {
    create_groups: Option<CreateGroupsOperation>,
    invite_members: Option<InviteMembersOperation>,
    add_group_members: Option<AddGroupMembersOperation>,
}

#[tokio::main]
async fn main() -> Result<()> {
    // ... äø­ē•„

    let args: Args = Args::from_args();
    let json_str = fs::read_to_string(&args.input)?;
    let operation = serde_json::from_str::<Operation>(&json_str)?;

    if let Some(op) = operation.create_groups {
        info!(">>>>>>>>>> Create groups");
        do_create_groups(&op).await
    }

    // ... äø­ē•„
}

API恫ćƒŖć‚Æć‚Øć‚¹ćƒˆć—ć¦ćƒ¬ć‚¹ćƒćƒ³ć‚¹JSONć‚’å–å¾—

reqwest悒ä½æć„ć¾ć™ć€‚

JSON悒ꉱ恆恮恧Cargo.toml恮featuresęŒ‡å®šć‚’ć—ć¾ć™ć€‚

reqwest = { version = "0.10.7", features = ["json"] }

reqwest::Client = reqwest::Client::new()ć§ä½œęˆć—ćŸć‚Æćƒ©ć‚¤ć‚¢ćƒ³ćƒˆć‚’ä½æć„ć¾ć™ć€‚
ćƒ”ć‚½ćƒƒćƒ‰ćƒć‚§ćƒ¼ćƒ³ć§ēˆ½ć‚„恋恫ę›øć‘ć¾ć™ć­šŸ˜

å…ˆć»ć©ć®serde悒ä½æć£ćŸę§‹é€ ä½“ć‚’ęŒ‡å®šć—ć¦.jsonćØć™ć‚Œć°ćƒ¬ć‚¹ćƒćƒ³ć‚¹JSONć‚’å¤‰ę›ć§ćć¾ć™ć€‚
res.json::<PostGroupsResponse>(...)恮éƒØåˆ†ć§ć™ć€‚

use std::env;

use anyhow::Result;
use serde::Deserialize;
use std::collections::HashMap;

const URL: &str = "https://api.bitbucket.org/1.0";

lazy_static! {
    static ref CLIENT: reqwest::Client = reqwest::Client::new();
    static ref USER_NAME: String =
        env::var("ATLRUS_USER_NAME").expect("You must specify ATLRUS_USER_NAME");
    static ref APP_PASSWORD: String =
        env::var("ATLRUS_APP_PASSWORD").expect("You must specify ATLRUS_APP_PASSWORD");
}

/// Actually.. there are more properties.
#[derive(Deserialize, Debug)]
pub struct PostGroupsResponse {
    pub name: String,
    pub slug: String,
}

/// Create a group in specified workspace.
pub async fn post_groups(workspaces_uuid: &str, group_name: &str) -> Result<PostGroupsResponse> {
    let url = format!(
        "{base_url}/groups/{workspace}",
        base_url = URL,
        workspace = workspaces_uuid,
    );

    let mut params = HashMap::new();
    params.insert("name", group_name);

    let res = CLIENT
        .post(&url)
        .basic_auth(USER_NAME.to_string(), Some(APP_PASSWORD.to_string()))
        .form(&params)
        .send()
        .await?;

    match res.status() {
        s if s.is_client_error() => bail!("Client error: {}. detail: {}", s, res.text().await?),
        s if s.is_server_error() => bail!("Server error: {}. detail: {}", s, res.text().await?),
        _ => Ok(res.json::<PostGroupsResponse>().await?),
    }
}

async/awaitć§éžåŒęœŸå‡¦ē†

äøŠčØ˜ć‚³ćƒ¼ćƒ‰ć‚’č¦‹ć¦ćæć¾ć—ć‚‡ć†ć€‚
async/awaitć§éžåŒęœŸå‡¦ē†ć‚’実ē¾ć—ć¦ć„ć¾ć™ć€‚

JavaScript恧ä½æ恆Promiseć«ä¼¼ćŸę¦‚åæµćØ恗恦态Rust恧ćÆFuturećŒć‚ć‚Šć¾ć™ć€‚
asyncé–¢ę•°ćÆåøø恫Futurećƒˆćƒ¬ć‚¤ćƒˆć‚’čæ”恗态awaitćÆFuture::poll恌Poll::Ready悒čæ”ć™ć¾ć§å¾…ć”ć¾ć™ć€‚

JavaScriptćØ恮違恄ćÆawaitć®ä½ē½®ć§ć™ć€‚
await futureImplemented恧ćÆćŖ恏futureImplemented.awaitć®ć‚ˆć†ć«ę›øćć¾ć™ć€‚

č¤‡ę•°ć®éžåŒęœŸå‡¦ē†ć‚’ćƒ”ć‚½ćƒƒćƒ‰ćƒć‚§ćƒ¼ćƒ³ć™ć‚‹ć‚±ćƒ¼ć‚¹ć§ćÆć‚Æćƒ¼ćƒ«ćŖć‚³ćƒ¼ćƒ‰ć«ćŖć‚Šć¾ć™šŸ˜Ž
JavaScript恠ćØ

const hoge = (await (await aaa).bbb).ccc;

恓悌恌Rust恠ćØ

let hoge = aaa.await.bbb.await.ccc;

éžåŒęœŸå‡¦ē†ćÆå¤±ę•—ć‚’å«ć‚€ć‚±ćƒ¼ć‚¹ćŒå¤šć„ć®ć§ć€å®Ÿéš›ć«ćÆawait?悒ä½æć„ć¾ć™ć‘ć©šŸ˜œ
reqwestć®ćƒ¬ć‚¹ćƒćƒ³ć‚¹ćÆtext()悄json::<T>()ć‚‚éžåŒęœŸå‡¦ē†ćŖ恮恧awai?t悒ä½æć„ć¾ć™ć€‚

asyncćŖmainé–¢ę•°

main悒asyncé–¢ę•°ć«ć™ć‚‹å “åˆćÆéžåŒęœŸćƒ©ćƒ³ć‚æ悤惠恌åæ…要恧恙怂
ꋘ悊ćÆćŖć‹ć£ćŸć®ć§tokio悒ä½æć„ć¾ć—ćŸć€‚

#[tokio::main]悒ä½æć„ćŸć„ć®ć§Cargo.toml恫featuresć‚’ęŒ‡å®šć—ć¾ć™ć€‚

tokio = { version = "0.2.22", features = ["macros"] }

恂ćØćÆmainé–¢ę•°ć«#[tokio::main]ć‚’ä»˜ć‘ć‚‹ć ć‘ć€‚
ć‚ˆćč¦‹ć‚‹ćØć€å…ˆć»ć©ć¾ć§ć®ć‚³ćƒ¼ćƒ‰ć‚µćƒ³ćƒ—ćƒ«ć«ć‚‚ä»˜ć„ć¦ć„ć¾ć™ć‚ˆšŸ‘

ć‚Øćƒ©ćƒ¼å‡¦ē†ć®ēµ±äø€

ć‚Øćƒ©ćƒ¼åž‹ćƒ©ć‚¤ćƒ–ćƒ©ćƒŖ恔ćØ恫ē•°ćŖć‚Šć¾ć™ć€‚
都åŗ¦å¤‰ę›ć™ć‚‹ć®ćÆč¾›ć™ćŽć‚‹ćŸć‚ć€anyhow悒ä½æć„ć¾ć™ć€‚

ć“ć‚Œć‚‚å…ˆć»ć©ć®ć‚³ćƒ¼ćƒ‰ä¾‹ć«ē™»å “ć—ć¦ć„ć¾ć™ć€‚
use anyhow::Result;ćØ宣čØ€ć™ć‚‹ć ć‘ć€‚

恓悌恧态ResultćÆstd::error::Errorćƒˆćƒ¬ć‚¤ćƒˆć‚’å®Ÿč£…ć™ć‚‹ć‚Øćƒ©ćƒ¼ć‚’ć™ć¹ć¦åŒę§˜ć«ę‰±ćˆć¾ć™ć€‚
ć¤ć¾ć‚Šhoge?ę§‹ę–‡ć‚’ć™ć¹ć¦å—ć‘å…„ć‚Œć¦ćć‚Œć‚‹ć‚ć‘ć§ć™ć€‚å¤Ŗć£č…¹šŸœ

他恫悂bail惞ć‚Æ惭悒ä½æć£ć¦ć„ć¾ć™ć€‚
bail!("...")ćØę›ø恏恠恑恧anyhowćŒę‰±ćˆć‚‹ć‚Øćƒ©ćƒ¼ć‚’ä½œęˆć§ćć¾ć™ć€‚

    match res.status() {
        s if s.is_client_error() => bail!("Client error: {}. detail: {}", s, res.text().await?),
        s if s.is_server_error() => bail!("Server error: {}. detail: {}", s, res.text().await?),
        _ => Ok(res.json::<PostGroupsResponse>().await?),
    }

今回ćÆä½æć„ć¾ć›ć‚“ć§ć—ćŸćŒć€ę”ä»¶ć‚’ęŗ€ćŸć•ćŖć„å “åˆć«ć‚Øćƒ©ćƒ¼ć‚’čæ”恙ensure惞ć‚Æ惭悂ä¾æåˆ©ć ćØę€ć„ć¾ć—ćŸć€‚

é…å»¶åˆęœŸåŒ–ć§ć‚·ćƒ³ć‚°ćƒ«ćƒˆćƒ³

ć‚³ćƒ³ćƒ‘ć‚¤ćƒ«ę™‚ć«ćÆē¢ŗå®šć—ćŖ恄恑恩态äø€åŗ¦ć ć‘ć®åˆęœŸåŒ–å‡¦ē†ć‚’ę›ø恍恟恄..
恝悓ćŖćØćć«lazy_static恧恙šŸ‘

å…ˆć»ć©ć®ć‚³ćƒ¼ćƒ‰ć«ć‚‚ć—ć‚Œć£ćØå…„ć‚Œć¦ć¾ć—ćŸć€‚
lazy_static! { ... }恮äø­ć«ę›øćć ć‘ć§ćŠę‰‹č»½ļ¼

#[macro_use]
extern crate lazy_static;

lazy_static! {
    static ref CLIENT: reqwest::Client = reqwest::Client::new();
    static ref USER_NAME: String =
        env::var("ATLRUS_USER_NAME").expect("You must specify ATLRUS_USER_NAME");
    static ref APP_PASSWORD: String =
        env::var("ATLRUS_APP_PASSWORD").expect("You must specify ATLRUS_APP_PASSWORD");
}

ćƒ­ć‚¬ćƒ¼ć§ćƒ­ć‚°ć‚’åć

ć„ć¤ć¾ć§ć‚‚print!恠ćØć¤ć‚‰ć„ć®ć§ćƒ­ć‚¬ćƒ¼ć‚’å…„ć‚Œć¾ć™ć€‚
log悒ä½æć„ć¾ć™ć€‚

logć®å®Ÿč£…ćÆåˆ‡ć‚Šé›¢ć•ć‚Œć¦ć„ć‚‹ćŸć‚ć€ä»„äø‹ć®ć„ćšć‚Œć‹ć‚’ä½æć„ć¾ć™ć€‚
ē¤¾å†…å‹‰å¼·ä¼šć§ć‚‚č©±é”Œć«äøŠćŒć£ćŸenv_loggerć«ć—ć¾ć™ć€‚

env_logger::init()ć§åˆęœŸåŒ–ć—ćŸć‚‰info!悄error!ćØå‘¼ć³å‡ŗć™ć ć‘ć§ć™ć€‚ćƒ©ć‚Æćƒćƒ³šŸ˜„
仄äø‹ćÆćƒ‡ćƒ•ć‚©ćƒ«ćƒˆćƒ­ć‚°ćƒ¬ćƒ™ćƒ«ć‚’INFOć«ć™ć‚‹ćŸć‚env_logger::from_env悒ä½æć£ć¦ć„ć¾ć™ćŒć€‚

#[macro_use]
extern crate log;

// ... äø­ē•„

#[tokio::main]
async fn main() -> Result<()> {
    env_logger::from_env(Env::default().default_filter_or("info")).init();

    // ... äø­ē•„
}

// ... äø­ē•„

async fn do_create_groups(op: &CreateGroupsOperation) {
    for group_name in op.group_names.iter() {
        match bitbucket::v1api::post_groups(&op.workspace_uuid, &group_name).await {
            Ok(group) => info!("Create a new group, {}!!", group.name),
            Err(err) => {
                error!("Fail to create a new group, {}..", group_name);
                error!("{}", err)
            }
        }
    }
}

// ... äø­ē•„

恂ćØ恌恍

ēµę§‹ćŖ惜ćƒŖćƒ„ćƒ¼ćƒ ć«ćŖć£ćŸć®ć§ć€å¾Œć»ć©1恤恮čؘäŗ‹ćØć—ć¦åˆ‡ć‚Šå‡ŗć™ć‹ć‚‚ć—ć‚Œć¾ć›ć‚“ć€‚
forꖇ悒ä½æć‚ćšć«async/awaitć™ć‚‹ę–¹ę³•ćØć‹ć‚‚ć£ćØć‚Ŗć‚·ćƒ£ćƒ¬ć«ć§ććć†ćŖ갗ćÆć—ć¦ć¾ć™..怂

ćć—ć¦ć€äŗˆęƒ³ä»„äøŠć«JavaScriptć®éžåŒęœŸå‡¦ē†ćØä¼¼ć¦ć¦č¦Ŗ恗ćæ恌ę²øćć¾ć—ćŸć€‚

čŖ­ć‚“恠恓ćØ/č“ć„ćŸć“ćØ

Rustć®éžåŒęœŸćƒ—ćƒ­ć‚°ćƒ©ćƒŸćƒ³ć‚°ć‚’ćƒžć‚¹ć‚æćƒ¼ć™ć‚‹

Rustć®éžåŒęœŸå‡¦ē†ćØę­“å²ć«ć¤ć„ć¦ć€ćØ恦悂äøåÆ§ć§åˆ†ć‹ć‚Šć‚„ć™ćčŖ¬ę˜Žć•ć‚Œć¦ć„ć¾ć™ć€‚

駆恑å‡ŗ恗Rustć‚Øćƒ³ć‚øćƒ‹ć‚¢ćØ恗恦ćÆć™ć¹ć¦ć‚’ē†č§£ć§ćć¾ć›ć‚“ćŒć€ę­“史ēš„ćŖēµŒē·ÆćÆTypeScript/JavaScript恮Promise -> async/await恫čæ‘ć„å°č±”ć‚’å—ć‘ć¾ć—ćŸć€‚

開ē™ŗ体éØ“ć‚’å¤‰ćˆć‚‹! Chrome DevTools Tips 7éø

Chrome恧惇惐惃悰恙悋ćØćć®ä¾æ利ćŖę‰‹ę³•ćŒē“¹ä»‹ć•ć‚Œć¦ć„ć¾ć™ć€‚

Exception恮ē™ŗē”Ÿē®‡ę‰€ć§č‡Ŗå‹•åœę­¢ćÆēŸ„悉ćŖć‹ć£ćŸ..怂

Todoist恫Boardsę©Ÿčƒ½ćŒčæ½åŠ 

ćƒ™ćƒ¼ć‚æē‰ˆć§ć™ćŒć‚«ćƒ³ćƒćƒ³ćƒœćƒ¼ćƒ‰ę©Ÿčƒ½ćŒęŠ•å…„ć•ć‚Œć¾ć—ćŸć€‚
ćƒ†ć‚¹ć‚æćƒ¼å‹Ÿé›†ć•ć‚Œć¦ć„ć‚‹ć®ć§ę°—ć«ćŖć‚‹ę–¹ćÆę˜Æ非šŸ’Ŗ

ć‚«ćƒ³ćƒćƒ³ć®åˆ—ćÆć‚»ć‚Æć‚·ćƒ§ćƒ³ćØäø€č‡“ć—ć¾ć™ć€‚
ć¾ćŸć€Boardč”Øē¤ŗćØListč”Øē¤ŗćÆć„ć¤ć§ć‚‚åˆ‡ć‚Šę›æćˆć‚‰ć‚Œć¾ć™ć€‚

ē§ćÆTodoćƒŖć‚¹ćƒˆć«ć‚¹ćƒ†ćƒ¼ć‚æć‚¹ć‚’ę±‚ć‚ćŖć„ć®ć§ć€ęć‚‰ćä½æ悏ćŖ恄ćØę€ć„ć¾ć™ć€‚
ć‚¹ćƒ†ćƒ¼ć‚æć‚¹ē®”ē†ćŒåæ…要恫ćŖć‚‹å “åˆćÆē“°åˆ†åŒ–ćŒč¶³ć‚ŠćŖ恄ćØę€ć£ć¦ć„ć‚‹ćŸć‚ć€‚

ćŖ恜TaskChute Cloud恮Ꙃ間ē®”ē†ćŒēŖ®å±ˆć§ćÆćŖ恄恮恋ļ¼Ÿ

åˆ†å˜ä½ć®ć‚æć‚¹ć‚Æē®”ē†ćÆēŖ®å±ˆćØꀝ恈悋恧恗悇恆怂ē§ć«ć‚‚ćć‚“ćŖę™‚ä»£ćŒć‚ć‚Šć¾ć—ćŸć€‚
恓恮čؘäŗ‹ćÆćć®ē–‘å•ć«ć—ć£ć‹ć‚Šč؀čŖžć•ć‚ŒćŸå›žē­”ć‚’ę•™ćˆć¦ćć‚Œć¾ć™ć€‚

å°Žå…„éƒØć®ę–‡ćŒć™ć¹ć¦ć‚’ē‰©čŖžć£ć¦ć„ć¾ć™ć€‚

ä¼‘ę—„ć«ć“ć®ć‚ˆć†ćŖā€ä½•ć‚‚恗ćŖ恄ā€ćŖ恩ćØć„ć†ę‹·å•ć‚’ē”˜ć‚“ć˜ć¦å—ć‘å…„悌悋äŗŗćÆć¾ćšå±…ćŖ恄恧恗悇恆怂ēµå±€ć®ćØć“ć‚ć€ä½•ć‚‚ę±ŗć‚ćšć€ä½•ć‚‚ć—ćŖ恄ćØäŗ‹å‰ć«ę±ŗ悁恟ćØć“ć‚ć§ć€ć„ć–ćć®ćØćć«ćŖć£ćŸć‚‰ä½•ć‹ć—ć‚‰ć‚’éøꊞ恛恚恫ćÆć„ć‚‰ć‚Œć¾ć›ć‚“ć€‚

ę˜Æ非态čؘäŗ‹ć‚’ęœ€å¾Œć¾ć§čŖ­ć‚“恧ćæ恦äø‹ć•ć„šŸ˜

äø–ē•Œäø€ć®ć‚³ćƒ¼ćƒć§ć™ć‚‰ć€Œē“ ē›“恘悃ćŖ恄äŗŗćÆę”¾ć£ć¦ćŠć‘ć°ć„ć„ć€ćØę€ć£ć¦ć„ćŸć€‚

ć‚³ćƒ¼ćƒćƒ³ć‚°ćÆå—ć‘ć‚‹å“ć®å•é”Œć§ć‚ć‚‹ćØć„ć†å°‘ć—éŽęæ€ćŖčؘäŗ‹ć§ć™ć€‚
ćØćÆ恄恈态ē§ć‚‚怎他äŗŗćÆå¤‰ćˆć‚‰ć‚ŒćŖ恄怏悒äæ”ć˜ć¦ć„ć‚‹ć‚æ惞ćŖć®ć§åŒę„Ÿć§ć™ć€‚

ć‚³ćƒ¼ćƒćƒ³ć‚°ć‚„ä»–äŗŗć‚’å¤‰ćˆć‚‹ć“ćØ悒仕äŗ‹ć«ć—ć¦ć„ć‚‹å “合ćÆćć®é™ć‚Šć§ć‚‚ćŖ恄ćØę€ć„ć¾ć™ćŒ..怂

č©¦ć—ćŸć“ćØ

IDEA恧databasećØ連ęŗ

DBeaverä½æć£ć¦ć„ć‚‹ć‹ć‚‰ć„ć‚‰ćŖ恄恋ćŖ..ćØę€ć£ć¦ć„ć¾ć—ćŸćŒę°—ć«ćŖć£ćŸć®ć§č©¦ć—ć¦ćæć¾ć—ćŸć€‚

ē§ćŒDBeaver恧åæ…要ćŖę©Ÿčƒ½ćÆ恻ćØć‚“ć©å®Ÿč£…ć•ć‚Œć¦ć„ć‚‹å°č±”..怂

  • ERå›³ć®č”Øē¤ŗ/ć‚øćƒ£ćƒ³ćƒ—
  • SQLćƒ•ć‚©ćƒ¼ćƒžćƒƒćƒˆ
  • č£œå®Œ
  • SQLć‚Øćƒ‡ć‚£ć‚æ
  • View
  • Windows悒ē‹¬ē«‹ć•ć›ć¦č¤‡ę•°ē”»é¢ä½æē”Ø

ćć‚Œć«åŠ ćˆć¦JetBrainsč£½å“ćŖ悉恧ćÆ恮ē‰¹å¾“ć‚‚ć‚ć‚Šć¾ć™ć€‚
ā€» åÆ¾č±”ćƒŖć‚½ćƒ¼ć‚¹ć«ęŽ„ē¶šć™ć‚‹åæ…č¦ćŒć‚ć‚Šć¾ć™

  • ć‚½ćƒ¼ć‚¹ć‚³ćƒ¼ćƒ‰(jsćƒ•ć‚”ć‚¤ćƒ«ćŖ恩)å†…ć®SQLę–‡ć§ć‚‚č£œå®Œ/ę¤œęŸ»
  • ć‚½ćƒ¼ć‚¹ć‚³ćƒ¼ćƒ‰ćØć®é€£ęŗć«ć‚ˆć‚‹ćƒ†ćƒ¼ćƒ–ćƒ«ćŖć©ć®å‘¼ć³å‡ŗć—å±„ę­“
  • Vimę“ä½œćŒåÆčƒ½..恝恆IdeaVim恌ä½æ恈悋恋悉恭!!

ēŸ„悉ćŖć„ć ć‘ć§ä»–ć«ć‚‚ćƒ”ćƒŖ惃惈ćÆ恂悋恧恗悇恆怂
個äŗŗēš„恫ćÆIdeaVimć®åŠ›ć§Vimę“ä½œć§ćć‚‹ć“ćØ恌ē›²ē‚¹ć§ć‚ć‚Šć€ę„Ÿå‹•ć—ć¾ć—ćŸw

čŖæć¹ćŸć“ćØ

怐Git怑git diffć®č”Œęœ«ć«ć€Ž^M怏恌č”Øē¤ŗ恕悌悋

Windows恧CRę”¹č”Œć®å·®åˆ†ćŒč”Øē¤ŗ恕悌悋恟悁恧恗恟怂
core.whitespace = cr-at-eolć‚’ęŒ‡å®šć™ć‚‹ćØč§£ę¶ˆć•ć‚Œć¾ć™ć€‚

仄äø‹ć«ć‚‚ć¾ćØć‚ć¾ć—ćŸć€‚

怐TypeScript怑sqlitećƒ‘ćƒƒć‚±ćƒ¼ć‚ø悒v4ć«ć‚¢ćƒƒćƒ—ćƒ‡ćƒ¼ćƒˆć—ćŸć‚‰ćƒ“ćƒ«ćƒ‰ć§ććŖ恄怂

v3恋悉v4恫惔ć‚øćƒ£ćƒ¼ć‚¢ćƒƒćƒ—ćƒ‡ćƒ¼ćƒˆć—ćŸć‚‰å½“ćŸć‚Šå‰ć®ć‚ˆć†ć«ćƒ“ćƒ«ćƒ‰ć§ććŖ恏ćŖć‚Šć¾ć—ćŸć€‚

å½±éŸæćŒć‚ć£ćŸć®ćÆ仄äø‹4ē‚¹ć§ć™ć€‚

  • db.allć®åž‹å¼•ę•°ć‚’T恋悉T[]ć«å¤‰ć‚ć£ćŸ
  • db.get恌undefined悒čæ”ć™ć‚ˆć†ć«ćŖć£ćŸ
  • ćƒ‰ćƒ©ć‚¤ćƒćØwrapperćŒåˆ†é›¢ć•ć‚ŒćŸ

꘎ē¤ŗēš„恫sqlite3ć‚’ćƒ‰ćƒ©ć‚¤ćƒćØć—ć¦ć‚¤ćƒ³ć‚¹ćƒˆćƒ¼ćƒ«ć™ć‚‹åæ…č¦ćŒć‚ć‚Šć¾ć™ć€‚

npm i sqlite3

README恫恂悋ćØćŠć‚Šć€åˆęœŸåŒ–ć®ę–¹ę³•ć‚‚å¤‰ć‚ć£ć¦ć„ć¾ć™ć€‚

import sqlite3 from 'sqlite3'
import { open } from 'sqlite'

(async () => {
  const db = await open({
    filename: "./db_system/database.sqlite",
    driver: sqlite3.Database,
  });
})();

ćŖ恊态import悒import sqlite from 'sqlite'恫恗恦await sqlite.open(...)恧ćÆćŖćœć‹å‹•ćć¾ć›ć‚“ć§ć—ćŸ..怂

怐Git怑Git恮ē®”ē†åŒ–恧ćÆę”¹č”Œć‚³ćƒ¼ćƒ‰ć‚’LFć«ć—ćŸć„

.gitattributesć§ę”¹č”Œć‚³ćƒ¼ćƒ‰ć«LFć‚’å¼·åˆ¶ć—ć¾ć™ć€‚
恓悌ćŖ悉恰autocrlf恮čØ­å®šć«ć‹ć‹ć‚ć‚‰ćšLFę”¹č”Œć‚’å¼·åˆ¶ć•ć›ć‚‹ć“ćØćŒć§ćć¾ć™ć€‚

* text=auto eol=lf

CRLF恌åæ…要ćŖćƒ•ć‚”ć‚¤ćƒ«ćÆ刄途čØ­å®šć—ć¾ć™ć€‚

*.bat text eol=crlf

怐Rust怑Optionć®å€¤ćŒå­˜åœØć™ć‚‹å “åˆć®ćæéžåŒęœŸå‡¦ē†ć‚’å®Ÿč”Œć—ćŸć„

éžåŒęœŸå‡¦ē†ć§ćÆmapć«ć‚ˆć‚‹ćƒ”ć‚½ćƒƒćƒ‰ćƒć‚§ćƒ¼ćƒ³ćŒé›£ć—ćć†ć ć£ćŸćŸć‚ć€ć“ć†ę›øć„ć¦ć„ć¾ć—ćŸć€‚

if operation.create_groups.is_some() {
    do_create_group(&operation.create_groups.unwrap()).await
}

恗恋恗态恓悌ćÆ恋ćŖć‚Šå†—é•·ć§ć™ć€‚
operation.create_groups恌SomećØåˆ†ć‹ć£ćŸę™‚ē‚¹ć§ć€äø­čŗ«ć ć‘ćŒę¬²ć—ć„..怂

let式ćØ惑ć‚æćƒ¼ćƒ³ćƒžćƒƒćƒć§ć‚·ćƒ³ćƒ—ćƒ«ć«ć‹ć‘ć¾ć—ćŸć€‚GOODšŸ˜„

if let Some(op) = operation.create_groups {
    do_create_group(&op).await
}

ę•“å‚™ć—ćŸć“ćØ

怐ć‚æćƒ¼ćƒŸćƒŠćƒ«ć€‘delta

Rust恧ę›ø恋悌恟ć‚Ŗć‚·ćƒ£ćƒ¬ćŖdiff CLI恮deltać‚’å°Žå…„ć—ć¾ć—ćŸć€‚

Windowsć§ć‚‚å‹•ćć¾ć™ć€‚ć•ć‚‰ć«ćÆcmd.exeć§ć‚‚å®Ÿē”Øēš„恫č”Øē¤ŗć•ć‚Œć¾ć™ļ¼

USB Type-C 恧ēµ¦é›»ćØHDMIå‡ŗåŠ›ć‚’å…¼ć­ć‚‹

ćƒŽćƒ¼ćƒˆćƒ‘ć‚½ć‚³ćƒ³ć®USB Type-Cćƒćƒ¼ćƒˆćŒå‹•ć‹ćŖ恏ćŖć£ć¦ć—ć¾ć„ć€USB Type-Cꎄē¶šć®2560x1440ćƒ‡ć‚£ć‚¹ćƒ—ćƒ¬ć‚¤ćŒä½æ恈ćŖ恏ćŖć‚Šć¾ć—ćŸć€‚
悂恆1恤恮Type-Cćƒćƒ¼ćƒˆćÆACć‚¢ćƒ€ćƒ—ć‚æ恋悉恮ēµ¦é›»ć ć£ćŸć®ć§ä½æć†ć‚ć‘ć«ćÆ恄恋恚..怂

USBćØēµ¦é›»ć®ēŸ„識

USB PDćØ恄恆ꦂåæµć‚’ćÆć˜ć‚ć¦ēŸ„ć‚Šć¾ć—ćŸć€‚

č£½å“ć‚’ęŽ¢ć™

ćć“ć§ä»„äø‹ć®č¦ä»¶ć‚’ęŗ€ćŸć™č£½å“ć‚’ęŽ¢ć—ć¾ć—ćŸć€‚

  • ēµŒē”±ć—恦PC恫ēµ¦é›»ć§ćć‚‹ (PC恫ēµ¦é›»ćŒåæ…要)
  • 60Hz恧2560x1440ē”»é¢å‡ŗåŠ›ć§ćć‚‹ (30Hz恧ćÆć‚«ć‚Æć‚«ć‚Æ)
  • ēµ¦é›»åÆčƒ½ć§Wi-fićƒ«ćƒ¼ć‚æ恫ꎄē¶šć§ćć‚‹ (USB-A)

ē‰¹ć«60Hz恮ē”»é¢å‡ŗ力ćÆåƾåæœč£½å“ćŒå°‘ćŖ恏态꜀ēµ‚ēš„恫仄äø‹č£½å“ć‚’č³¼å…„ć—ć¾ć—ćŸć€‚
ćŠå€¤ę®µćÆ恝悌ćŖć‚Šć§ć™ćŒć€č£½å“čŖ¬ę˜Žć‚‚äøåÆ§ć§äæ”é ¼ć§ććć†ć ć£ćŸć‹ć‚‰ć§ć™ć€‚

Club 3D CSV-1592 ćÆ态USB ć‚æ悤惗 C 7-in-1 惏惖 to HDMI 4K60Hz /SD-TF ć‚«ćƒ¼ćƒ‰ć‚¹ćƒ­ćƒƒćƒˆ / 2x USB ć‚æ悤惗 A / USB ć‚æ悤惗 C PD / RJ45ć®ćƒćƒ–ć§ć™ć€‚USB ć‚æ悤惗 Cćƒ›ć‚¹ćƒˆć‹ć‚‰ę˜ åƒćƒ»éŸ³ę„½ć®č¦–č“ć€å‘Øč¾ŗćƒ‡ćƒć‚¤ć‚¹ćøć®å……é›»ć€ćƒ‡ćƒ¼ć‚æ通äæ”ćŒč”Œćˆć¾ć™ć€‚HDMIć®ęœ€å¤§č§£åƒåŗ¦ć‚’4K60Hz恧ä½æē”Øć™ć‚‹ćŸć‚ć®ćÆ态恔ä½æē”Øć®ćƒ›ć‚¹ćƒˆćŒDP 1.4 Alt mode ć‚’ć‚µćƒćƒ¼ćƒˆć—ć¦ć„ć‚‹åæ…č¦ćŒć‚ć‚Šć¾ć™ć€‚

HDMIć®ęœ€å¤§č§£åƒåŗ¦ć‚’4K60HzćØ恂悋恮恧ē”»é¢å‡ŗ力ćÆ恧恍恝恆怂
30HzćÆć‚«ć‚Æć‚«ć‚Æć§č€ćˆć‚‰ć‚Œć¾ć›ć‚“ć‹ć‚‰ć­šŸ˜œ

ć‚¢ćƒƒćƒ—ć‚¹ćƒˆćƒŖćƒ¼ćƒ ćÆć€ćƒ›ć‚¹ćƒˆęŽ„ē¶šē”Ø恮USB ć‚æ悤惗-C ć‚Ŗć‚¹ ć‚³ćƒć‚Æć‚æć§ć™ć€‚ćƒ€ć‚¦ćƒ³ć‚¹ćƒˆćƒŖćƒ¼ćƒ ćÆ HDMI ćƒ”ć‚¹ć‚³ćƒć‚Æć‚æ态USB ć‚æ悤惗-A 3.0恌äŗŒć¤ļ¼ˆäø€ć¤ćÆBC 1.2å……é›»ę©Ÿčƒ½ä»˜ćļ¼‰ć€PDå……é›»ćŠć‚ˆć³ćƒ‡ćƒ¼ć‚æ通äæ”åÆčƒ½ćŖUSB ć‚æ悤惗-Cćƒ”ć‚¹ć‚³ćƒć‚Æć‚æ态Micro SD ć‚«ćƒ¼ćƒ‰ć‚¹ćƒ­ćƒƒćƒˆļ¼‘åŸŗ态SD ć‚«ćƒ¼ćƒ‰ć‚¹ćƒ­ćƒƒćƒˆļ¼‘åŸŗ态RJ45ć‚®ć‚¬ć‚¤ćƒ¼ć‚µćƒćƒƒćƒˆć§ć™ć€‚ć‚µć‚¤ć‚ŗćÆ态13.6 x 3.4 x 1.4 cm恧恙怂重恕ćÆ69g恧恙怂

USB ć‚æ悤惗-A 3.0恌äŗŒć¤ļ¼ˆäø€ć¤ćÆBC 1.2å……é›»ę©Ÿčƒ½ä»˜ćļ¼‰ćØ恂悋恮恧Wi-fićƒ«ćƒ¼ć‚æ恫悂ꎄē¶šć§ććć†ć§ć™ć€‚

USB ć‚æ悤惗-A恮åøÆ域ćÆ5Gbps恧态USBć‚æ悤惗-A恮äŗŒć¤ć®ćƒćƒ¼ćƒˆć®ć†ć”äø€ć¤ćŒć€ęœ€å¤§7.5Wļ¼ˆ5V@1.5Aļ¼‰å……電恮BC1.2ć‚’ć‚µćƒćƒ¼ćƒˆć—ć¦ć„ć¾ć™ć€‚USB ć‚æ悤惗-C PDćÆć€ćƒ‡ćƒ¼ć‚æ通äæ”ćØå……é›»ćŒč”Œćˆć€100Wļ¼ˆ20V/5Aļ¼‰ć¾ć§å……é›»ć§ćć¾ć™ć€‚ćƒ‡ćƒ¼ć‚æ通äæ”ćÆć§ćć¾ć›ć‚“ć€‚SD/Micro SDćÆć€ć‚»ć‚­ćƒ„ć‚¢ćƒ‡ć‚øć‚æ惫v3.0 UHS-I ć‚’ć‚µćƒćƒ¼ćƒˆć‚µćƒćƒ¼ćƒˆć—ć¾ć™ć€‚RJ45ć‚®ć‚¬ćƒ“ćƒƒćƒˆć‚¤ćƒ¼ć‚µćƒ¼ćƒćƒƒćƒˆćÆ态10Mbps/100Mbps/1000Mbpsć‚’ć‚µćƒćƒ¼ćƒˆć—ć¾ć™ć€‚

USB ć‚æ悤惗-C PDćÆć€ćƒ‡ćƒ¼ć‚æ通äæ”ćØå……é›»ćŒč”Œćˆć€100Wļ¼ˆ20V/5Aļ¼‰ć¾ć§å……é›»ć§ćć¾ć™ćØ恂悋恮恧ēµ¦é›»ć‚‚ć„ć‘ć¾ć™ć€‚

å®Ÿéš›ć©ć†ć ć£ćŸć‹?

今恮ćØ恓悍态äŗˆęƒ³é€šć‚Šå‹•ć„ć¦ć„ć¾ć™šŸ‘
恗恰悉恏ä½æć£ć¦ćæćŖ恄ćØåˆ†ć‹ć‚Šć¾ć›ć‚“ćŒć€äø€ę—¦ē”»é¢ćŒč˜‡ć£ć¦ęŗ€č¶³šŸ˜

恔ćŖćæ恫ꎄē¶šå…ˆć®ćƒ‡ć‚£ć‚¹ćƒ—ćƒ¬ć‚¤ćÆ仄äø‹ć§ć™ć€‚


今週恮ćƒŖćƒŖćƒ¼ć‚¹

Togowl v2.13.0 ļ½ž 2.13.2

ć‚æć‚¹ć‚Æ态ć‚Øćƒ³ćƒˆćƒŖ态惗惭ć‚ø悧ć‚Æ惈ćŖ恩悒ćƒŖćƒ­ćƒ¼ćƒ‰ć™ć‚‹ćƒœć‚æćƒ³ć‚’čæ½åŠ 

通äæ”ć‚Øćƒ©ćƒ¼ć‚„ćƒ‡ćƒ¼ć‚æäøę•“åˆćŒē™ŗē”Ÿć—ćŸćØćć€ć‚¢ćƒ—ćƒŖć‚±ćƒ¼ć‚·ćƒ§ćƒ³ć®ćƒŖćƒ­ćƒ¼ćƒ‰ćŖć—ć«å¾©åø°ć§ćć¾ć™ć€‚
ć¾ćŸć€ć‚æć‚¹ć‚Æć®ćƒ­ćƒ¼ćƒ‰äø­ćÆåøøć«ć‚¤ćƒ³ć‚øć‚±ćƒ¼ć‚æćƒ¼ćƒ–ćƒ­ćƒƒć‚Æ悒č”Øē¤ŗć™ć‚‹ć‚ˆć†ć«ć—ć¾ć—ćŸć€‚

ćć®ä»–

遂恫Rustć§å‹•ććƒ¢ćƒŽć‚’ä½œć‚ŒćŸć“ćØćÆå¤§ććŖäø€ę­©ć ćØę€ć£ć¦ć„ć¾ć™ć€‚

å®¶ć®ćƒ”ć‚¤ćƒ³ćƒ‡ć‚£ć‚¹ćƒ—ćƒ¬ć‚¤ćŒä½æ恈ćŖ恏ćŖć£ćŸćØ恍ćÆäŗˆęƒ³ä»„äøŠć«ēµ¶ęœ›ć‚’ę„Ÿć˜ć¾ć—ćŸć€‚
ę™®ę®µå½“ćŸć‚Šå‰ć«ć‚ć‚‹ē’°å¢ƒ..ćć®ć“ćØć«ę„Ÿč¬ć™ć‚‹ę°—ęŒć”ć‚’åæ˜ć‚ŒćŖć„ć‚ˆć†ć«ćØę€ć„ć¾ć—ćŸć­

ćć—ć¦ę—„ęœ¬FALCOMć®č»Œč·”ć‚·ćƒŖćƒ¼ć‚ŗęœ€ę–°ä½œ..å‰µć®č»Œč·”ćŒć„ć‚ˆć„ć‚ˆä»Šé€±ē™ŗå£²ć§ć™ļ¼

Togowlć®čƒŒę™Æē”»åƒ1恫悂čØ­å®šć—ć¦ćƒ†ćƒ³ć‚·ćƒ§ćƒ³ć‚’äøŠć’恤恤态ęœØ金ćÆ休ćæ悒ćØć£ćŸć®ć§ęŗ–å‚™ć‚‚OK怂
今週/ę„é€±ćÆåÆ‚ć—ć„ćƒ¬ćƒćƒ¼ćƒˆć«ćŖ悋ćØę€ć„ć¾ć™ćŒć”äŗ†ę‰æ恏恠恕恄šŸ˜…


  1. TogowlćÆä»»ę„ć®čƒŒę™Æē”»åƒć‚’čح定åÆčƒ½ć§ć‚ć‚Šć€ćƒŖć‚½ćƒ¼ć‚¹ć«åˆ©ē”Øć—ć¦ć„ć‚‹ć‚ć‘ć§ćÆć‚ć‚Šć¾ć›ć‚“ ↩︎