@things-factory/shell 10.0.0-beta.7 → 10.0.0-beta.72

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/_index.html CHANGED
@@ -5,7 +5,7 @@
5
5
  <meta name="google" content="notranslate" />
6
6
  <title>Things Factory App</title>
7
7
  <meta name="generator" content="Things Factory Starter Kit" />
8
- <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
8
+ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover" />
9
9
  <meta name="description" content="Reimagining Software" />
10
10
 
11
11
  <base href="/" />
@@ -1,4 +1,6 @@
1
1
  {
2
+ "id": "/",
3
+ "scope": "/",
2
4
  "name": "Things Factory",
3
5
  "short_name": "Factory",
4
6
  "description": "Things Factory",
@@ -171,21 +171,39 @@ addEventListener('notificationclick', async event => {
171
171
  return
172
172
  }
173
173
 
174
+ /*
175
+ * PWA 알림 클릭 처리 정책:
176
+ * 1) includeUncontrolled — SW 가 아직 controller 가 아닌 윈도우 (방금 설치 / 새로 열린 PWA) 도
177
+ * 매칭에 포함. 누락 시 클라가 있어도 못 찾고 fallback 으로 새 브라우저 창이 뜨는 회귀.
178
+ * 2) 같은 url 이미 열려있으면 그 창 focus.
179
+ * 3) 같은 origin 의 윈도우 있으면 navigate + focus — 알림 URL 로 이동 보장. 단순 focus
180
+ * 만 하면 사용자가 보기엔 "아무 일도 안 일어남" + OS 가 브라우저 fallback 띄움.
181
+ * 4) 매칭 없으면 openWindow — PWA 가 등록된 origin/scope 면 OS 가 자동 PWA 로 라우팅.
182
+ */
174
183
  event.waitUntil(
175
- clients
176
- .matchAll({
177
- type: 'window'
184
+ (async () => {
185
+ const list = await clients.matchAll({
186
+ type: 'window',
187
+ includeUncontrolled: true
178
188
  })
179
- .then(function (clients) {
180
- for (var i = 0; i < clients.length; i++) {
181
- var client = clients[i]
182
- if ('focus' in client) {
183
- return client.focus()
184
- }
189
+ for (const c of list) {
190
+ if (c.url === url && 'focus' in c) {
191
+ return c.focus()
185
192
  }
186
- if (clients.openWindow) {
187
- return clients.openWindow(url)
193
+ }
194
+ for (const c of list) {
195
+ if (c.url.startsWith(self.location.origin) && 'focus' in c) {
196
+ if ('navigate' in c) {
197
+ try {
198
+ await (c as WindowClient).navigate(url)
199
+ } catch {
200
+ /* cross-origin nav 거부 등 — focus 만이라도 */
201
+ }
202
+ }
203
+ return c.focus()
188
204
  }
189
- })
205
+ }
206
+ return clients.openWindow(url)
207
+ })()
190
208
  )
191
209
  })
@@ -1,2 +1,3 @@
1
- export declare function initMiddlewares(app: any): void;
1
+ import Koa from 'koa';
2
+ export declare function initMiddlewares(app: Koa): void;
2
3
  export * from './domain-middleware.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/middlewares/index.ts"],"names":[],"mappings":";;AAIA,0CAoCC;;AAxCD,6CAAoD;AAEpD,iEAAyD;AAEzD,SAAgB,eAAe,CAAC,GAAG;IACjC,GAAG,CAAC,eAAe,GAAG,YAAM,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAA;IAEtD,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE;QAC/B,YAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACnB,CAAC,CAAC,CAAA;IAEF;;;OAGG;IACH,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QAC9B,IAAI,CAAC;YACH,MAAM,IAAI,EAAE,CAAA;QACd,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,MAAM,GAAG,GAAG,EAAE,MAAM,IAAI,GAAG,CAAA;YACnC,OAAO,CAAC,IAAI,GAAG,GAAG,EAAE,OAAO,CAAA;YAE3B,yCAAyC;YACzC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,CAAA;QACzC,CAAC;IACH,CAAC,CAAC,CAAA;IAEF;;;OAGG;IACH,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QAC9B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAA;QAEhC,IAAI,MAAM,IAAI,MAAM,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YACpD,OAAO,MAAM,IAAA,uCAAgB,EAAC,OAAO,EAAE,IAAI,CAAC,CAAA;QAC9C,CAAC;QAED,MAAM,IAAI,EAAE,CAAA;IACd,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,iEAAsC","sourcesContent":["import { config, logger } from '@things-factory/env'\n\nimport { domainMiddleware } from './domain-middleware.js'\n\nexport function initMiddlewares(app) {\n app.subdomainOffset = config.get('subdomainOffset', 2)\n\n app.on('error', (err, context) => {\n logger.error(err)\n })\n\n /*\n * Catching downstream errors\n * - recommend to use context.throw, context.assert\n */\n app.use(async (context, next) => {\n try {\n await next()\n } catch (err) {\n context.status = err?.status || 500\n context.body = err?.message\n\n // emitting error to app.on('error', ...)\n context.app.emit('error', err, context)\n }\n })\n\n /*\n * post:graphql 에 대해서는 domain을 확인한다.\n * graphql app을 router에 적용하지 못하기 때문임.\n */\n app.use(async (context, next) => {\n const { method, path } = context\n\n if (method == 'POST' && path.startsWith('/graphql')) {\n return await domainMiddleware(context, next)\n }\n\n await next()\n })\n}\n\nexport * from './domain-middleware.js'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/middlewares/index.ts"],"names":[],"mappings":";;AAMA,0CAoCC;;AAxCD,6CAAoD;AAEpD,iEAAyD;AAEzD,SAAgB,eAAe,CAAC,GAAQ;IACtC,GAAG,CAAC,eAAe,GAAG,YAAM,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAA;IAEtD,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE;QAC/B,YAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACnB,CAAC,CAAC,CAAA;IAEF;;;OAGG;IACH,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QAC9B,IAAI,CAAC;YACH,MAAM,IAAI,EAAE,CAAA;QACd,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,MAAM,GAAG,GAAG,EAAE,MAAM,IAAI,GAAG,CAAA;YACnC,OAAO,CAAC,IAAI,GAAG,GAAG,EAAE,OAAO,CAAA;YAE3B,yCAAyC;YACzC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,CAAA;QACzC,CAAC;IACH,CAAC,CAAC,CAAA;IAEF;;;OAGG;IACH,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QAC9B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAA;QAEhC,IAAI,MAAM,IAAI,MAAM,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YACpD,OAAO,MAAM,IAAA,uCAAgB,EAAC,OAAO,EAAE,IAAI,CAAC,CAAA;QAC9C,CAAC;QAED,MAAM,IAAI,EAAE,CAAA;IACd,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,iEAAsC","sourcesContent":["import Koa from 'koa'\n\nimport { config, logger } from '@things-factory/env'\n\nimport { domainMiddleware } from './domain-middleware.js'\n\nexport function initMiddlewares(app: Koa) {\n app.subdomainOffset = config.get('subdomainOffset', 2)\n\n app.on('error', (err, context) => {\n logger.error(err)\n })\n\n /*\n * Catching downstream errors\n * - recommend to use context.throw, context.assert\n */\n app.use(async (context, next) => {\n try {\n await next()\n } catch (err) {\n context.status = err?.status || 500\n context.body = err?.message\n\n // emitting error to app.on('error', ...)\n context.app.emit('error', err, context)\n }\n })\n\n /*\n * post:graphql 에 대해서는 domain을 확인한다.\n * graphql app을 router에 적용하지 못하기 때문임.\n */\n app.use(async (context, next) => {\n const { method, path } = context\n\n if (method == 'POST' && path.startsWith('/graphql')) {\n return await domainMiddleware(context, next)\n }\n\n await next()\n })\n}\n\nexport * from './domain-middleware.js'\n"]}