Knowledge Updates

Observations while developing web applications and creating great software.

  • Migrating Apple Account purchases between accounts ↗

    Apple:

    You can choose to migrate apps, music, and other content you’ve purchased from Apple on a secondary Apple Account to a primary Apple Account. The secondary Apple Account might be an account that’s used only for purchases.

  • async-provider ↗

    Ryan Florence released this a few months ago:

    A lightweight, type-safe async context management system for JavaScript applications. Perfect for server-side applications where you need to share request-scoped values across components and functions.

    This is a small wrapper on top of AsyncLocalStorage to provide a simple and type-safe API for request scoped values.

    This is expected to be the recommended solution for type-safe context in upcoming React Router middleware.

    import { createContext, provide, pull } from "@ryanflorence/async-provider";
    
    // 1. ✅ Create your contexts
    let userContext = createContext<User>();
    let dbContext = createContext<Database>();
    
    async function myHandleRequest(req: Request) {
      // setup context values
      let user = await myAuthenticateUser(req);
      let db = myCreateDatabaseConnection(user);
    
      // 2. ✅ Provide contexts
      let html = await provide(
        new Map([
          [userContext, user],
          [dbContext, db],
        ]),
        async () => {
          // run your app code within this context
          let result = await renderApp();
          // Can return values from provider callback
          return result;
        },
      );
    
      return new Response(html, {
        headers: { "Content-Type": "text/html" },
      });
    }
    
    // 3. ✅ Pull context from anywhere
    function renderApp() {
      let user = pull(userContext);
      let db = pull(dbContext);
    
      // Use user and db...
    }

  • New encoding format in Turbo Stream v3 ↗

    Turbo Stream by Jacob Ebey is a streaming data transport for built-in JavaScript features such as Promises, Dates, RegExps, Maps, Sets and more.

    import { decode, encode } from "turbo-stream";
    
    const encodedStream = encode(Promise.resolve(42));
    const decoded = await decode(encodedStream);
    console.log(decoded); // 42

    Turbo Stream powers single-fetch data loaders in React Router which enables streaming Promises from server loaders.

    import type { Route } from "./+types/my-route";
    
    export async function loader({}: Route.LoaderArgs) {
      // note this is NOT awaited
      let nonCriticalData = new Promise((res) =>
        setTimeout(() => res("non-critical"), 5000)
      );
    
      let criticalData = await new Promise((res) =>
        setTimeout(() => res("critical"), 300)
      );
    
      return { nonCriticalData, criticalData };
    }
    

    Turbo Stream v3 is out with support for a new encoding format which supports ReadableStream and many other JS features.

    This means it’ll be coming to React Router very soon. While it’s possible to encode streams into promises, it’ll be good to see React Router support streams natively.

  • Developer philosophy ↗

    qntm:

    A few weeks ago at work we had a talk where senior developers (including me) were invited to spend around five minutes each talking about our personal software development philosophies. The idea was for us to share our years of experience with our more junior developers.

    After the session, I felt that it might be valuable to write my own thoughts up, and add a little more detail. So here we are.

    Avoid ground-up rewrites:

    By the time the ground-up rewrite starts to seem like a good idea, avoidable mistakes have already been made. This is a scenario which you can see coming from a long way out and you can, and must, actively steer away from.

    Warning signs to watch for: compounding technical debt. Increasing difficulty in making seemingly simple changes to code. Difficulty in documenting/commenting code. Difficulty in onboarding new developers. Dwindling numbers of people who know how particular areas of the codebase actually work. Bugs nobody understands.

    Compounding complexity must be fought at every turn. Alternate between phases of expansion (new features) and consolidation.

    Simplicity:

    If you budgeted your time properly (see above), you have time to go back and see if you can do better. C.f. the old chess adage, “When you see a good move, look for a better one.” And another difficult-to-source quote, “I apologise for writing such a long letter, but I didn’t have time to write a short one.”

    And perhaps my favorite topic: automating good practice — which I’ll invite you to read on the original post.

    Kent Beck says, “Make the change easy, then make the easy change.” I think about that a lot.

    Go read qntm’s wisdom and then go read his science fiction.

  • Kneeboard ↗

    Community generated repository of interactive checklists that work on your computer, tablet, or phone by Armadeus Demarzi.

    It’s beautiful.

    Via X